summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/DEPS2
-rw-r--r--chrome/common/child_process_info.cc6
-rw-r--r--chrome/common/chrome_paths.cc14
-rw-r--r--chrome/common/chrome_paths.h4
-rw-r--r--chrome/common/chrome_paths_internal.h4
-rw-r--r--chrome/common/chrome_paths_mac.mm4
-rw-r--r--chrome/common/chrome_switches.cc114
-rw-r--r--chrome/common/chrome_switches.h36
-rw-r--r--chrome/common/chrome_version_info.cc3
-rw-r--r--chrome/common/common.sb12
-rw-r--r--chrome/common/common_param_traits.cc16
-rw-r--r--chrome/common/database_util.cc16
-rw-r--r--chrome/common/dx_diag_node.cc9
-rw-r--r--chrome/common/dx_diag_node.h3
-rw-r--r--chrome/common/env_vars.cc3
-rw-r--r--chrome/common/env_vars.h1
-rw-r--r--chrome/common/extensions/api/extension_api.json97
-rw-r--r--chrome/common/extensions/docs/a11y.html6
-rw-r--r--chrome/common/extensions/docs/api_index.html6
-rw-r--r--chrome/common/extensions/docs/api_other.html8
-rw-r--r--chrome/common/extensions/docs/autoupdate.html6
-rw-r--r--chrome/common/extensions/docs/background_pages.html6
-rw-r--r--chrome/common/extensions/docs/bookmarks.html6
-rw-r--r--chrome/common/extensions/docs/browserAction.html8
-rwxr-xr-xchrome/common/extensions/docs/build/build.py15
-rw-r--r--chrome/common/extensions/docs/build/directory.py44
-rw-r--r--chrome/common/extensions/docs/content_scripts.html6
-rw-r--r--chrome/common/extensions/docs/contextMenus.html38
-rw-r--r--chrome/common/extensions/docs/cookies.html6
-rw-r--r--chrome/common/extensions/docs/crx.html6
-rw-r--r--chrome/common/extensions/docs/css/ApiRefStyles.css23
-rw-r--r--chrome/common/extensions/docs/devguide.html6
-rw-r--r--chrome/common/extensions/docs/docs.html6
-rw-r--r--chrome/common/extensions/docs/events.html6
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/extension-docs.zipbin0 -> 74406 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/extension-docs/background.html466
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/extension-docs/icon-128.pngbin0 -> 8449 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/extension-docs/icon-16.pngbin0 -> 47675 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/extension-docs/manifest.json16
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/simple-example.zip (renamed from chrome/common/extensions/docs/examples/api/omnibox.zip)bin1101 -> 1208 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/simple-example/background.html (renamed from chrome/common/extensions/docs/examples/api/omnibox/background.html)0
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/simple-example/manifest.json (renamed from chrome/common/extensions/docs/examples/api/omnibox/manifest.json)1
-rw-r--r--chrome/common/extensions/docs/examples/api/processes/process_monitor.zipbin0 -> 5226 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/processes/show_tabs.zipbin6137 -> 6112 bytes
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark.zipbin101161 -> 316130 bytes
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/README.txt11
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/background.html95
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-1.4.2.min.js154
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-ui-1.8.4.custom.min.js0
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.client.js0
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.dashes.js237
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.js0
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.min.js1
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.navigate.js0
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.valuelabels.js0
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/options.html533
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/util/sorttable.js489
-rw-r--r--chrome/common/extensions/docs/examples/extensions/benchmark/util/table2CSV.js90
-rw-r--r--chrome/common/extensions/docs/experimental.clipboard.html6
-rw-r--r--chrome/common/extensions/docs/experimental.contextMenus.html6
-rw-r--r--chrome/common/extensions/docs/experimental.cookies.html6
-rw-r--r--chrome/common/extensions/docs/experimental.history.html6
-rw-r--r--chrome/common/extensions/docs/experimental.html6
-rw-r--r--chrome/common/extensions/docs/experimental.idle.html6
-rw-r--r--chrome/common/extensions/docs/experimental.infobars.html6
-rw-r--r--chrome/common/extensions/docs/experimental.omnibox.html8
-rw-r--r--chrome/common/extensions/docs/experimental.processes.html6
-rw-r--r--chrome/common/extensions/docs/experimental.proxy.html6
-rw-r--r--chrome/common/extensions/docs/experimental.sidebar.html6
-rw-r--r--chrome/common/extensions/docs/experimental.webNavigation.html6
-rw-r--r--chrome/common/extensions/docs/experimental.webRequest.html6
-rw-r--r--chrome/common/extensions/docs/extension.html8
-rw-r--r--chrome/common/extensions/docs/external_extensions.html6
-rw-r--r--chrome/common/extensions/docs/faq.html31
-rw-r--r--chrome/common/extensions/docs/getstarted.html18
-rw-r--r--chrome/common/extensions/docs/history.html6
-rw-r--r--chrome/common/extensions/docs/hosting.html6
-rw-r--r--chrome/common/extensions/docs/i18n-messages.html6
-rw-r--r--chrome/common/extensions/docs/i18n.html8
-rw-r--r--chrome/common/extensions/docs/idle.html6
-rw-r--r--chrome/common/extensions/docs/images/toggle_sprite.pngbin0 -> 417 bytes
-rw-r--r--chrome/common/extensions/docs/images/toolsmenu.gifbin2355 -> 1555 bytes
-rw-r--r--chrome/common/extensions/docs/index.html6
-rw-r--r--chrome/common/extensions/docs/js/sidebar.js84
-rw-r--r--chrome/common/extensions/docs/management.html268
-rw-r--r--chrome/common/extensions/docs/manifest.html123
-rw-r--r--chrome/common/extensions/docs/match_patterns.html6
-rw-r--r--chrome/common/extensions/docs/messaging.html6
-rw-r--r--chrome/common/extensions/docs/notifications.html6
-rw-r--r--chrome/common/extensions/docs/npapi.html6
-rw-r--r--chrome/common/extensions/docs/options.html6
-rw-r--r--chrome/common/extensions/docs/override.html8
-rw-r--r--chrome/common/extensions/docs/overview.html6
-rw-r--r--chrome/common/extensions/docs/packaging.html6
-rw-r--r--chrome/common/extensions/docs/pageAction.html6
-rw-r--r--chrome/common/extensions/docs/permission_warnings.html11
-rw-r--r--chrome/common/extensions/docs/samples.html90
-rw-r--r--chrome/common/extensions/docs/samples.json56
-rw-r--r--chrome/common/extensions/docs/static/api_other.html2
-rw-r--r--chrome/common/extensions/docs/static/browserAction.html2
-rw-r--r--chrome/common/extensions/docs/static/content_scripts.html2
-rw-r--r--chrome/common/extensions/docs/static/crx.html6
-rw-r--r--chrome/common/extensions/docs/static/faq.html25
-rw-r--r--chrome/common/extensions/docs/static/getstarted.html14
-rw-r--r--chrome/common/extensions/docs/static/i18n.html2
-rw-r--r--chrome/common/extensions/docs/static/management.html17
-rw-r--r--chrome/common/extensions/docs/static/manifest.html109
-rw-r--r--chrome/common/extensions/docs/static/override.html2
-rw-r--r--chrome/common/extensions/docs/tabs.html260
-rw-r--r--chrome/common/extensions/docs/template/api_template.html7
-rw-r--r--chrome/common/extensions/docs/template/page_shell.html1
-rw-r--r--chrome/common/extensions/docs/themes.html6
-rw-r--r--chrome/common/extensions/docs/tut_analytics.html6
-rw-r--r--chrome/common/extensions/docs/tut_debugging.html6
-rw-r--r--chrome/common/extensions/docs/tut_oauth.html6
-rw-r--r--chrome/common/extensions/docs/tutorials.html6
-rw-r--r--chrome/common/extensions/docs/whats_new.html6
-rw-r--r--chrome/common/extensions/docs/windows.html6
-rw-r--r--chrome/common/extensions/docs/xhr.html6
-rw-r--r--chrome/common/extensions/extension.cc345
-rw-r--r--chrome/common/extensions/extension.h606
-rw-r--r--chrome/common/extensions/extension_action.h2
-rw-r--r--chrome/common/extensions/extension_constants.cc3
-rw-r--r--chrome/common/extensions/extension_constants.h2
-rw-r--r--chrome/common/extensions/extension_file_util.cc47
-rw-r--r--chrome/common/extensions/extension_file_util.h8
-rw-r--r--chrome/common/extensions/extension_file_util_unittest.cc10
-rw-r--r--chrome/common/extensions/extension_l10n_util.cc16
-rw-r--r--chrome/common/extensions/extension_l10n_util.h2
-rw-r--r--chrome/common/extensions/extension_localization_peer.cc4
-rw-r--r--chrome/common/extensions/extension_localization_peer.h1
-rw-r--r--chrome/common/extensions/extension_localization_peer_unittest.cc5
-rw-r--r--chrome/common/extensions/extension_manifests_unittest.cc131
-rw-r--r--chrome/common/extensions/extension_message_bundle.cc34
-rw-r--r--chrome/common/extensions/extension_resource.cc7
-rw-r--r--chrome/common/extensions/extension_unittest.cc124
-rw-r--r--chrome/common/extensions/extension_unpacker.cc20
-rw-r--r--chrome/common/extensions/url_pattern.cc51
-rw-r--r--chrome/common/extensions/url_pattern.h38
-rw-r--r--chrome/common/extensions/url_pattern_unittest.cc69
-rw-r--r--chrome/common/extensions/user_script.cc2
-rw-r--r--chrome/common/extensions/user_script_unittest.cc9
-rw-r--r--chrome/common/file_system/file_system_dispatcher.cc7
-rw-r--r--chrome/common/file_system/file_system_dispatcher.h3
-rw-r--r--chrome/common/file_system/webfilesystem_callback_dispatcher.cc2
-rw-r--r--chrome/common/file_system/webfilesystem_callback_dispatcher.h8
-rw-r--r--chrome/common/file_system/webfilewriter_impl.cc4
-rw-r--r--chrome/common/font_loader_mac.mm7
-rw-r--r--chrome/common/gpu_create_command_buffer_config.cc16
-rw-r--r--chrome/common/gpu_create_command_buffer_config.h12
-rw-r--r--chrome/common/gpu_info.cc10
-rw-r--r--chrome/common/gpu_info.h8
-rw-r--r--chrome/common/gpu_messages.cc19
-rw-r--r--chrome/common/gpu_messages.h1
-rw-r--r--chrome/common/gpu_messages_internal.h54
-rw-r--r--chrome/common/gpu_messages_unittest.cc5
-rw-r--r--chrome/common/gpu_native_window_handle.h42
-rw-r--r--chrome/common/gpu_param_traits.h1
-rw-r--r--chrome/common/gpu_video_common.cc14
-rw-r--r--chrome/common/important_file_writer.cc11
-rw-r--r--chrome/common/json_pref_store.h2
-rw-r--r--chrome/common/libxml_utils.cc4
-rw-r--r--chrome/common/logging_chrome.cc179
-rw-r--r--chrome/common/logging_chrome.h8
-rw-r--r--chrome/common/logging_chrome_uitest.cc5
-rw-r--r--chrome/common/metrics_helpers.cc18
-rw-r--r--chrome/common/net/gaia/gaia_authenticator2.cc51
-rw-r--r--chrome/common/net/gaia/gaia_authenticator2_unittest.cc6
-rw-r--r--chrome/common/net/gaia/gaia_constants.cc4
-rw-r--r--chrome/common/net/gaia/gaia_constants.h2
-rw-r--r--chrome/common/net/gaia/google_service_auth_error.h4
-rw-r--r--chrome/common/net/raw_host_resolver_proc.cc28
-rw-r--r--chrome/common/net/raw_host_resolver_proc.h40
-rw-r--r--chrome/common/net/test_url_fetcher_factory.cc14
-rw-r--r--chrome/common/net/test_url_fetcher_factory.h19
-rw-r--r--chrome/common/net/url_fetcher.cc14
-rw-r--r--chrome/common/net/url_fetcher_unittest.cc23
-rw-r--r--chrome/common/net/url_request_context_getter.cc2
-rw-r--r--chrome/common/net/url_request_context_getter.h9
-rw-r--r--chrome/common/net/x509_certificate_model.cc36
-rw-r--r--chrome/common/net/x509_certificate_model.h24
-rw-r--r--chrome/common/net/x509_certificate_model_nss.cc9
-rw-r--r--chrome/common/net/x509_certificate_model_openssl.cc116
-rw-r--r--chrome/common/notification_registrar.cc23
-rw-r--r--chrome/common/notification_registrar.h6
-rw-r--r--chrome/common/notification_type.h75
-rw-r--r--chrome/common/plugin_messages_internal.h7
-rw-r--r--chrome/common/policy_constants.cc3
-rw-r--r--chrome/common/policy_constants.h3
-rw-r--r--chrome/common/pref_names.cc42
-rw-r--r--chrome/common/pref_names.h16
-rw-r--r--chrome/common/pref_store.h2
-rw-r--r--chrome/common/render_messages.cc25
-rw-r--r--chrome/common/render_messages.h15
-rw-r--r--chrome/common/render_messages_internal.h122
-rw-r--r--chrome/common/render_messages_params.cc8
-rw-r--r--chrome/common/render_messages_params.h4
-rw-r--r--chrome/common/resource_dispatcher_unittest.cc16
-rw-r--r--chrome/common/sandbox_init_wrapper_mac.cc16
-rw-r--r--chrome/common/sandbox_mac.h189
-rw-r--r--chrome/common/sandbox_mac.mm316
-rw-r--r--chrome/common/sandbox_mac_diraccess_unittest.mm129
-rw-r--r--chrome/common/sandbox_mac_fontloading_unittest.mm32
-rw-r--r--chrome/common/sandbox_mac_unittest_helper.h2
-rw-r--r--chrome/common/sandbox_mac_unittest_helper.mm18
-rw-r--r--chrome/common/sandbox_policy.cc8
-rw-r--r--chrome/common/security_filter_peer.cc6
-rw-r--r--chrome/common/security_filter_peer.h1
-rw-r--r--chrome/common/service_process_util.cc4
-rw-r--r--chrome/common/speech_input_result.h33
-rw-r--r--chrome/common/url_constants.cc15
-rw-r--r--chrome/common/url_constants.h12
-rw-r--r--chrome/common/view_types.h1
-rw-r--r--chrome/common/webkit_param_traits.cc7
-rw-r--r--chrome/common/webmessageportchannel_impl.cc4
215 files changed, 5689 insertions, 1853 deletions
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
index 93d6fc0..18175ac 100644
--- a/chrome/common/DEPS
+++ b/chrome/common/DEPS
@@ -7,7 +7,7 @@ include_rules = [
"+media/base",
"+remoting/client/plugin",
"+sandbox/src",
- "+skia/include",
+ "+skia",
"+webkit/glue",
# Other libraries.
diff --git a/chrome/common/child_process_info.cc b/chrome/common/child_process_info.cc
index 41d066b..bd94ff2 100644
--- a/chrome/common/child_process_info.cc
+++ b/chrome/common/child_process_info.cc
@@ -135,9 +135,9 @@ std::string ChildProcessInfo::GenerateRandomChannelID(void* instance) {
// 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()));
+ return base::StringPrintf("%d.%p.%d",
+ base::GetCurrentProcId(), instance,
+ base::RandInt(0, std::numeric_limits<int>::max()));
}
// static
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc
index 6f77510..181cf0a 100644
--- a/chrome/common/chrome_paths.cc
+++ b/chrome/common/chrome_paths.cc
@@ -295,6 +295,20 @@ bool PathProvider(int key, FilePath* result) {
break;
}
#endif
+#if defined(OS_MACOSX)
+ case chrome::DIR_MANAGED_PREFS: {
+ if (!GetLocalLibraryDirectory(&cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("Managed Preferences"));
+ char* login = getlogin();
+ if (!login)
+ return false;
+ cur = cur.AppendASCII(login);
+ if (!file_util::PathExists(cur)) // we don't want to create this
+ return false;
+ break;
+ }
+#endif
default:
return false;
}
diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h
index 65538a7..63037c6 100644
--- a/chrome/common/chrome_paths.h
+++ b/chrome/common/chrome_paths.h
@@ -42,6 +42,10 @@ enum {
// to set policies for chrome. This directory
// contains subdirectories.
#endif
+#if defined(OS_MACOSX)
+ DIR_MANAGED_PREFS, // Directory that stores the managed prefs plist
+ // files for the current user.
+#endif
FILE_RESOURCE_MODULE, // Full path and filename of the module that
// contains embedded resources (version,
// strings, images, etc.).
diff --git a/chrome/common/chrome_paths_internal.h b/chrome/common/chrome_paths_internal.h
index 38fbac2..6671e25 100644
--- a/chrome/common/chrome_paths_internal.h
+++ b/chrome/common/chrome_paths_internal.h
@@ -55,6 +55,10 @@ void SetOverrideVersionedDirectory(const FilePath* path);
// framework are things that also depend on the framework, such as the helper
// app bundle.
FilePath GetFrameworkBundlePath();
+
+// Get the local library directory.
+bool GetLocalLibraryDirectory(FilePath* result);
+
#endif // OS_MACOSX
} // namespace chrome
diff --git a/chrome/common/chrome_paths_mac.mm b/chrome/common/chrome_paths_mac.mm
index c7db483..b87b397 100644
--- a/chrome/common/chrome_paths_mac.mm
+++ b/chrome/common/chrome_paths_mac.mm
@@ -105,4 +105,8 @@ FilePath GetFrameworkBundlePath() {
return GetVersionedDirectory().Append(kFrameworkName);
}
+bool GetLocalLibraryDirectory(FilePath* result) {
+ return mac_util::GetLocalDirectory(NSLibraryDirectory, result);
+}
+
} // namespace chrome
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 9847a38..ff007df 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -100,6 +100,10 @@ const char kCloudPrintProxyId[] = "cloud-print-proxy-id";
// print service has been enabled (see enable-cloud-print).
const char kCloudPrintServiceURL[] = "cloud-print-service";
+// Causes the browser process to inspect loaded and registered DLLs for
+// known conflicts and warn the user.
+const char kConflictingModulesCheck[] = "conflicting-modules-check";
+
// 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.
@@ -144,9 +148,6 @@ const char kDisableBackgroundNetworking[] = "disable-background-networking";
// 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";
-
// Disable click-to-play for blocked plug-ins.
const char kDisableClickToPlay[] = "disable-click-to-play";
@@ -194,6 +195,10 @@ const char kDisableGeolocation[] = "disable-geolocation";
// Disable the GLSL translator.
const char kDisableGLSLTranslator[] = "disable-glsl-translator";
+// Disable the thread that crashes the GPU process if it stops responding to
+// messages.
+const char kDisableGpuWatchdog[] = "disable-gpu-watchdog";
+
// Suppresses hang monitor dialogs in renderer processes. This may allow slow
// unload handlers on a page to prevent the tab from closing, but the Task
// Manager can be used to terminate the offending process in this case.
@@ -293,9 +298,6 @@ const char kDisableSyncBookmarks[] = "disable-sync-bookmarks";
// Disable syncing of extensions.
const char kDisableSyncExtensions[] = "disable-sync-extensions";
-// Disable syncing browser passwords.
-const char kDisableSyncPasswords[] = "disable-sync-passwords";
-
// Disable syncing of preferences.
const char kDisableSyncPreferences[] = "disable-sync-preferences";
@@ -387,6 +389,9 @@ const char kEnableCloudPrintProxy[] = "enable-cloud-print-proxy";
// Enables the Cloud Print dialog hosting code.
const char kEnableCloudPrint[] = "enable-cloud-print";
+// Enable the Confirm to Quit experiment.
+const char kEnableConfirmToQuit[] = "enable-confirm-to-quit";
+
// Enables establishing a backup TCP connection if a specified timeout is
// exceeded.
const char kEnableConnectBackupJobs[] = "enable-connect-backup-jobs";
@@ -403,6 +408,11 @@ const char kEnableDefaultApps[] = "enable-default-apps";
// Enables device motion events.
const char kEnableDeviceMotion[] = "enable-device-motion";
+// Enable DNS side checking of certificates. Still experimental, should only
+// be used by developers at the current time.
+const char kEnableDNSCertProvenanceChecking[] =
+ "enable-dns-cert-provenance-checking";
+
const char kEnableDNSSECCerts[] = "enable-dnssec-certs";
// Enables extension APIs that are in development.
@@ -428,16 +438,10 @@ const char kEnableIPv6[] = "enable-ipv6";
// 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";
-// Is match preview enabled?
-const char kEnableMatchPreview[] = "enable-match-preview";
-
// Allows reporting memory info (JS heap size) to page.
const char kEnableMemoryInfo[] = "enable-memory-info";
@@ -456,6 +460,9 @@ const char kEnableNaClDebug[] = "enable-nacl-debug";
// Enable Native Web Worker support.
const char kEnableNativeWebWorkers[] = "enable-native-web-workers";
+// Is the predictive varition of instant enabled?
+const char kEnablePredictiveInstant[] = "enable-predictive-instant";
+
// This applies only when the process type is "service". Enables the
// Chromoting Host Process within the service process.
const char kEnableRemoting[] = "enable-remoting";
@@ -464,6 +471,9 @@ const char kEnableRemoting[] = "enable-remoting";
const char kEnableResourceContentSettings[] =
"enable-resource-content-settings";
+// Enable speculative prerendering of pages.
+const char kEnablePagePrerender[] = "enable-page-prerender";
+
// Enable speculative TCP/IP preconnection.
const char kEnablePreconnect[] = "enable-preconnect";
@@ -477,9 +487,6 @@ const char kEnablePrintPreview[] = "enable-print-preview";
// parameter to indicate if the provider should be the default.
const char kEnableSearchProviderApiV2[] = "enable-search-provider-api-v2";
-// Enables the secure infobars. Non-default until the kinks are worked out.
-const char kEnableSecureInfoBars[] = "enable-secure-infobars";
-
// Enables 0-RTT HTTPS handshakes.
const char kEnableSnapStart[] = "enable-snap-start";
@@ -492,6 +499,9 @@ const char kEnableSync[] = "enable-sync";
// Enable syncing browser autofill.
const char kEnableSyncAutofill[] = "enable-sync-autofill";
+// Enable syncing browser passwords.
+const char kEnableSyncPasswords[] = "enable-sync-passwords";
+
// Enable syncing browser sessions.
const char kEnableSyncSessions[] = "enable-sync-sessions";
@@ -501,12 +511,19 @@ const char kEnableSyncTypedUrls[] = "enable-sync-typed-urls";
// Enable tabbed options, ie: dom-ui version of options window.
const char kEnableTabbedOptions[] = "enable-tabbed-options";
+// Enable use of experimental TCP sockets API for sending data in the
+// SYN packet.
+const char kEnableTcpFastOpen[] = "enable-tcp-fastopen";
+
// Enables TopSites.
const char kEnableTopSites[] = "enable-top-sites";
// Whether or not the touch events API is exposed.
const char kEnableTouch[] = "enable-touch";
+// Is verbatim instant enabled?
+const char kEnableVerbatimInstant[] = "enable-verbatim-instant";
+
// Enables the option to show tabs as a vertical stack down the side of the
// browser window.
const char kEnableVerticalTabs[] = "enable-vertical-tabs";
@@ -515,10 +532,6 @@ const char kEnableVerticalTabs[] = "enable-vertical-tabs";
// 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";
@@ -593,6 +606,10 @@ const char kForceAppsPromoVisible[] = "force-apps-promo-visible";
// current details.
const char kForceFieldTestNameAndValue[] = "force-fieldtest";
+// Forces the internal PDF plugin to be used for this run, even if it's disabled
+// by default. Used for testing.
+const char kForceInternalPDFPlugin[] = "force-internal-pdf";
+
// Force renderer accessibility to be on instead of enabling it on demand when
// a screen reader is detected. The disable-renderer-accessibility switch
// overrides this if present.
@@ -664,6 +681,10 @@ const char kInProcessWebGL[] = "in-process-webgl";
// Causes the browser to launch directly in incognito mode.
const char kIncognito[] = "incognito";
+// URL to use for instant. If specified this overrides the url from the
+// TemplateURL.
+const char kInstantURL[] = "instant-url";
+
// Runs the Native Client inside the renderer process.
const char kInternalNaCl[] = "internal-nacl";
@@ -980,14 +1001,12 @@ 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";
+// Allow insecure XMPP connections for sync (for testing).
+const char kSyncAllowInsecureXmppConnection[] =
+ "sync-allow-insecure-xmpp-connection";
-// Email used for sync.
-const char kSyncEmail[] = "email";
+// Invalidate any login info passed into sync's XMPP connection.
+const char kSyncInvalidateXmppLogin[] = "sync-invalidate-xmpp-login";
// Use the SyncerThread implementation that matches up with the old pthread
// impl semantics, but using Chrome synchronization primitives. The only
@@ -998,26 +1017,15 @@ const char kSyncerThreadTimedStop[] = "syncer-thread-timed-stop";
// Override the default notification method for sync.
const char kSyncNotificationMethod[] = "sync-notification-method";
-// Override the default host used for sync notifications.
+// Override the default host used for sync notifications. Can be either
+// "host" or "host:port".
const char kSyncNotificationHost[] = "sync-notification-host";
-// 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";
-// Control Sync XMPP client settings.
-const char kSyncUseSslTcp[] = "use-ssl-tcp";
-
-// Control Sync XMPP client settings.
-const char kSyncUseCacheInvalidation[] = "use-cache-invalidation";
+// Try to connect to XMPP using SSLTCP first (for testing).
+const char kSyncTrySsltcpFirstForXmpp[] = "sync-try-ssltcp-first-for-xmpp";
// Pass the name of the current running automated test to Chrome.
const char kTestName[] = "test-name";
@@ -1056,12 +1064,20 @@ const char kIgnoreCertificateErrors[] = "ignore-certificate-errors";
// Set the maximum SPDY sessions per domain.
const char kMaxSpdySessionsPerDomain[] = "max-spdy-sessions-per-domain";
+// Set the maximum concurrent streams over a SPDY session.
+const char kMaxSpdyConcurrentStreams[] = "max-spdy-concurrent-streams";
+
// Grant unlimited quota to store files to this process.
// Used for testing Pepper's FileRef/FileIO/FileSystem implementations.
// DO NOT USE FOR OTHER PURPOSES.
// TODO(dumi): remove the switch when we have a real quota implementation.
const char kUnlimitedQuotaForFiles[] = "unlimited-quota-for-files";
+// This is for testing IndexedDB and will give any website you visit unlimited
+// quota in IndexedDB. This should only be used for development and not general
+// browsing. It is ignored in single process mode.
+const char kUnlimitedQuotaForIndexedDB[] = "unlimited-quota-for-indexeddb";
+
// Use the low fragmentation heap for the CRT.
const char kUseLowFragHeapCrt[] = "use-lf-heap";
@@ -1175,12 +1191,9 @@ const char kCompressSystemFeedback[] = "compress-sys-feedback";
// switch separates chrome code from the rest of ChromeOS.
const char kForceStubLibcros[] = "force-stub-libcros";
-// Disables DOMUI menu and use gtk menu instead.
-const char kDisableDOMUIMenu[] = "disable-domui-menu";
+// Enables DOMUI menu.
+const char kEnableDOMUIMenu[] = "enable-domui-menu";
-#ifndef NDEBUG
-extern const char kDOMUIMenuUrl[] = "domui-menu-url";
-#endif
#endif
#if defined(OS_LINUX)
@@ -1199,8 +1212,6 @@ const char kUseSystemSSL[] = "use-system-ssl";
// 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";
// Bypass the error dialog when the profile lock couldn't be attained.
@@ -1225,6 +1236,13 @@ const char kEnableExposeForTabs[] = "enable-expose-for-tabs";
// 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 revert to the old WorkerPool implementation.
+// This will be removed once we either fix the Mac WorkerPool
+// implementation, or completely switch to the shared (with Linux)
+// implementation.
+const char kDisableLinuxWorkerPool[] = "disable-linux-worker-pool";
#else
// Enable Kiosk mode.
const char kKioskMode[] = "kiosk";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 14e3ae3..49c3e49 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -42,6 +42,7 @@ extern const char kCheckForUpdateIntervalSec[];
extern const char kChromeFrame[];
extern const char kCloudPrintProxyId[];
extern const char kCloudPrintServiceURL[];
+extern const char kConflictingModulesCheck[];
extern const char kCountry[];
extern const char kDebugPrint[];
extern const char kDiagnostics[];
@@ -52,7 +53,6 @@ extern const char kDisableAudio[];
extern const char kDisableAuthNegotiateCnameLookup[];
extern const char kDisableBackgroundNetworking[];
extern const char kDisableBackingStoreLimit[];
-extern const char kDisableByteRangeSupport[];
extern const char kDisableClickToPlay[];
extern const char kDisableConnectBackupJobs[];
extern const char kDisableContentPrefetch[];
@@ -67,6 +67,7 @@ extern const char kDisableExtensions[];
extern const char kDisableFileSystem[];
extern const char kDisableGLSLTranslator[];
extern const char kDisableGeolocation[];
+extern const char kDisableGpuWatchdog[];
extern const char kDisableHangMonitor[];
extern const char kDisableHistoryQuickProvider[];
extern const char kDisableHistoryURLProvider[];
@@ -96,7 +97,6 @@ extern const char kDisableSyncApps[];
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 kDisableTabCloseableStateWatcher[];
@@ -121,45 +121,48 @@ extern const char kEnableBenchmarking[];
extern const char kEnableClearServerData[];
extern const char kEnableCloudPrintProxy[];
extern const char kEnableCloudPrint[];
+extern const char kEnableConfirmToQuit[];
extern const char kEnableConnectBackupJobs[];
extern const char kEnableContentPrefetch[];
extern const char kEnableDefaultApps[];
extern const char kEnableDeviceMotion[];
+extern const char kEnableDNSCertProvenanceChecking[];
extern const char kEnableDNSSECCerts[];
extern const char kEnableExperimentalExtensionApis[];
extern const char kEnableExtensionTimelineApi[];
extern const char kEnableFastback[];
extern const char kEnableFileCookies[];
extern const char kEnableGPUPlugin[];
-extern const char kEnableGPURendering[];
extern const char kEnableIPv6[];
extern const char kEnableLogging[];
-extern const char kEnableMatchPreview[];
extern const char kEnableMemoryInfo[];
extern const char kEnableMonitorProfile[];
extern const char kEnableNaCl[];
extern const char kEnableNaClDebug[];
extern const char kEnableNativeWebWorkers[];
+extern const char kEnablePagePrerender[];
extern const char kEnablePreconnect[];
+extern const char kEnablePredictiveInstant[];
extern const char kEnablePreparsedJsCaching[];
extern const char kEnablePrintPreview[];
extern const char kEnableRemoting[];
extern const char kEnableResourceContentSettings[];
extern const char kEnableSearchProviderApiV2[];
-extern const char kEnableSecureInfoBars[];
extern const char kEnableSnapStart[];
extern const char kEnableStatsTable[];
extern const char kEnableSync[];
extern const char kEnableSyncAutofill[];
+extern const char kEnableSyncPasswords[];
extern const char kEnableSyncPreferences[];
extern const char kEnableSyncSessions[];
extern const char kEnableSyncTypedUrls[];
extern const char kEnableTabbedOptions[];
+extern const char kEnableTcpFastOpen[];
extern const char kEnableTopSites[];
extern const char kEnableTouch[];
+extern const char kEnableVerbatimInstant[];
extern const char kEnableVerticalTabs[];
extern const char kEnableVideoFullscreen[];
-extern const char kEnableVideoLayering[];
extern const char kEnableVideoLogging[];
extern const char kEnableWatchdog[];
extern const char kEnableXSSAuditor[];
@@ -177,6 +180,7 @@ extern const char kFileDescriptorLimit[];
extern const char kFirstRun[];
extern const char kForceAppsPromoVisible[];
extern const char kForceFieldTestNameAndValue[];
+extern const char kForceInternalPDFPlugin[];
extern const char kForceRendererAccessibility[];
extern const char kGpuLauncher[];
extern const char kGpuProcess[];
@@ -193,6 +197,7 @@ extern const char kImportFromFile[];
extern const char kInProcessPlugins[];
extern const char kInProcessWebGL[];
extern const char kIncognito[];
+extern const char kInstantURL[];
extern const char kInternalNaCl[];
extern const char kInternalPepper[];
extern const char kJavaScriptFlags[];
@@ -275,18 +280,13 @@ 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 kSyncAllowInsecureXmppConnection[];
+extern const char kSyncInvalidateXmppLogin[];
extern const char kSyncerThreadTimedStop[];
extern const char kSyncNotificationMethod[];
extern const char kSyncNotificationHost[];
-extern const char kSyncPassword[];
-extern const char kSyncPort[];
-extern const char kSyncServer[];
extern const char kSyncServiceURL[];
-extern const char kSyncUseSslTcp[];
-extern const char kSyncUseCacheInvalidation[];
+extern const char kSyncTrySsltcpFirstForXmpp[];
extern const char kTestNaClSandbox[];
extern const char kTestName[];
extern const char kTestSandbox[];
@@ -298,7 +298,9 @@ extern const char kUninstall[];
extern const char kUseSpdy[];
extern const char kIgnoreCertificateErrors[];
extern const char kMaxSpdySessionsPerDomain[];
+extern const char kMaxSpdyConcurrentStreams[];
extern const char kUnlimitedQuotaForFiles[];
+extern const char kUnlimitedQuotaForIndexedDB[];
extern const char kUseLowFragHeapCrt[];
extern const char kUserAgent[];
extern const char kUserDataDir[];
@@ -335,10 +337,7 @@ extern const char kStubCros[];
extern const char kScreenSaverUrl[];
extern const char kCompressSystemFeedback[];
extern const char kForceStubLibcros[];
-extern const char kDisableDOMUIMenu[];
-#ifndef NDEBUG
-extern const char kDOMUIMenuUrl[];
-#endif
+extern const char kEnableDOMUIMenu[];
#endif
#if defined(OS_LINUX)
@@ -361,6 +360,7 @@ extern const char kPasswordStore[];
extern const char kDisableHolePunching[];
extern const char kEnableExposeForTabs[];
extern const char kEnableSandboxLogging[];
+extern const char kDisableLinuxWorkerPool[];
#else
extern const char kKioskMode[];
#endif
diff --git a/chrome/common/chrome_version_info.cc b/chrome/common/chrome_version_info.cc
index a26f81f..5157c4a 100644
--- a/chrome/common/chrome_version_info.cc
+++ b/chrome/common/chrome_version_info.cc
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/file_version_info.h"
#include "base/string_util.h"
+#include "base/thread_restrictions.h"
#include "build/build_config.h"
namespace chrome {
@@ -16,6 +17,8 @@ namespace chrome {
// FileVersionInfo for the current module.
VersionInfo::VersionInfo() {
+ // The current module is already loaded in memory, so this will be cheap.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
version_info_.reset(FileVersionInfo::CreateFileVersionInfoForCurrentModule());
}
diff --git a/chrome/common/common.sb b/chrome/common/common.sb
index f8d4f1c..4b5c4f5 100644
--- a/chrome/common/common.sb
+++ b/chrome/common/common.sb
@@ -11,7 +11,7 @@
; printing on sandbox exceptions; this functionality only exists on 10.6. The
; --enable-sandbox-logging flag or system versions <10.6 cause this flag to
; expand to an empty string. http://crbug.com/26621
-(deny default DISABLE_SANDBOX_DENIAL_LOGGING)
+(deny default @DISABLE_SANDBOX_DENIAL_LOGGING@)
; Support for programmatically enabling verbose debugging.
;ENABLE_LOGGING (debug deny)
@@ -26,13 +26,11 @@
; 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
+(allow file-read*
+ (regex #"^/System/Library/Frameworks($|/)")
+ (regex #"^/System/Library/PrivateFrameworks($|/)")
+ (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_param_traits.cc b/chrome/common/common_param_traits.cc
index d18c6c5..2fd8bdd 100644
--- a/chrome/common/common_param_traits.cc
+++ b/chrome/common/common_param_traits.cc
@@ -138,7 +138,7 @@ bool ParamTraits<gfx::Point>::Read(const Message* m, void** iter,
}
void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::string* l) {
- l->append(StringPrintf("(%d, %d)", p.x(), p.y()));
+ l->append(base::StringPrintf("(%d, %d)", p.x(), p.y()));
}
@@ -164,8 +164,8 @@ bool ParamTraits<gfx::Rect>::Read(const Message* m, void** iter, gfx::Rect* r) {
}
void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::string* l) {
- l->append(StringPrintf("(%d, %d, %d, %d)", p.x(), p.y(),
- p.width(), p.height()));
+ l->append(base::StringPrintf("(%d, %d, %d, %d)", p.x(), p.y(),
+ p.width(), p.height()));
}
@@ -185,7 +185,7 @@ bool ParamTraits<gfx::Size>::Read(const Message* m, void** iter, gfx::Size* r) {
}
void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::string* l) {
- l->append(StringPrintf("(%d, %d)", p.width(), p.height()));
+ l->append(base::StringPrintf("(%d, %d)", p.width(), p.height()));
}
void ParamTraits<ContentSetting>::Write(Message* m, const param_type& p) {
@@ -435,8 +435,8 @@ bool ParamTraits<ThumbnailScore>::Read(const Message* m, void** iter,
}
void ParamTraits<ThumbnailScore>::Log(const param_type& p, std::string* l) {
- l->append(StringPrintf("(%f, %d, %d)",
- p.boring_score, p.good_clipping, p.at_top));
+ l->append(base::StringPrintf("(%f, %d, %d)",
+ p.boring_score, p.good_clipping, p.at_top));
}
template <>
@@ -454,7 +454,7 @@ struct ParamTraits<Geoposition::ErrorCode> {
}
static void Log(const param_type& p, std::string* l) {
int error_code = p;
- l->append(StringPrintf("<Geoposition::ErrorCode>%d", error_code));
+ l->append(base::StringPrintf("<Geoposition::ErrorCode>%d", error_code));
}
};
@@ -488,7 +488,7 @@ bool ParamTraits<Geoposition>::Read(
void ParamTraits<Geoposition>::Log(const Geoposition& p, std::string* l) {
l->append(
- StringPrintf(
+ base::StringPrintf(
"<Geoposition>"
"%.6f %.6f %.6f %.6f "
"%.6f %.6f %.6f ",
diff --git a/chrome/common/database_util.cc b/chrome/common/database_util.cc
index 412debc..ea4e2cc 100644
--- a/chrome/common/database_util.cc
+++ b/chrome/common/database_util.cc
@@ -18,8 +18,8 @@ WebKitClient::FileHandle DatabaseUtil::databaseOpenFile(
IPC::PlatformFileForTransit file_handle =
IPC::InvalidPlatformFileForTransit();
- scoped_refptr<IPC::SyncMessageFilter> filter =
- ChildThread::current()->sync_message_filter();
+ scoped_refptr<IPC::SyncMessageFilter> filter(
+ ChildThread::current()->sync_message_filter());
filter->Send(new ViewHostMsg_DatabaseOpenFile(
vfs_file_name, desired_flags, &file_handle));
@@ -29,8 +29,8 @@ WebKitClient::FileHandle DatabaseUtil::databaseOpenFile(
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();
+ scoped_refptr<IPC::SyncMessageFilter> filter(
+ ChildThread::current()->sync_message_filter());
filter->Send(new ViewHostMsg_DatabaseDeleteFile(
vfs_file_name, sync_dir, &rv));
return rv;
@@ -38,16 +38,16 @@ int DatabaseUtil::databaseDeleteFile(
long DatabaseUtil::databaseGetFileAttributes(const WebString& vfs_file_name) {
int32 rv = -1;
- scoped_refptr<IPC::SyncMessageFilter> filter =
- ChildThread::current()->sync_message_filter();
+ 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();
+ 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/dx_diag_node.cc b/chrome/common/dx_diag_node.cc
new file mode 100644
index 0000000..85beb5b
--- /dev/null
+++ b/chrome/common/dx_diag_node.cc
@@ -0,0 +1,9 @@
+// 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/dx_diag_node.h"
+
+DxDiagNode::DxDiagNode() {}
+
+DxDiagNode::~DxDiagNode() {}
diff --git a/chrome/common/dx_diag_node.h b/chrome/common/dx_diag_node.h
index 9f20d92..6522213 100644
--- a/chrome/common/dx_diag_node.h
+++ b/chrome/common/dx_diag_node.h
@@ -12,6 +12,9 @@
#include <string>
struct DxDiagNode {
+ DxDiagNode();
+ ~DxDiagNode();
+
std::map<std::string, std::string> values;
std::map<std::string, DxDiagNode> children;
};
diff --git a/chrome/common/env_vars.cc b/chrome/common/env_vars.cc
index dc2648c..f63d3e4 100644
--- a/chrome/common/env_vars.cc
+++ b/chrome/common/env_vars.cc
@@ -14,6 +14,9 @@ const char kHeadless[] = "CHROME_HEADLESS";
// The name of the log file.
const char kLogFileName[] = "CHROME_LOG_FILE";
+// The name of the session log directory when logged in to ChromeOS.
+const char kSessionLogDir[] = "CHROMEOS_SESSION_LOG_DIR";
+
// If this environment variable is set, Chrome on Windows will log
// to Event Tracing for Windows.
const char kEtwLogging[] = "CHROME_ETW_LOGGING";
diff --git a/chrome/common/env_vars.h b/chrome/common/env_vars.h
index e9984d2..320a0b4 100644
--- a/chrome/common/env_vars.h
+++ b/chrome/common/env_vars.h
@@ -12,6 +12,7 @@ namespace env_vars {
extern const char kHeadless[];
extern const char kLogFileName[];
+extern const char kSessionLogDir[];
extern const char kEtwLogging[];
extern const char kShowRestart[];
extern const char kRestartInfo[];
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 3fdd1ce..45d9409 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -503,7 +503,12 @@
"optional": true,
"description": "The speak options. This parameter is currently ignored.",
"properties": {
- "languageName": {
+ "enqueue": {
+ "type": "boolean",
+ "optional": true,
+ "description": "If true, enqueues this utterance if TTS is already in progress. If false (the default), interrupts any current speech and flushes the speech queue before speaking this new utterance."
+ },
+ "languageName": {
"type": "string",
"optional": true,
"description": "The language name for synthesis specified in the form <language>-<locale>, e.g. en-US, en-GB, fr-CA, zh-CN, etc."
@@ -804,6 +809,7 @@
"index": {"type": "integer", "minimum": 0, "description": "The zero-based index of the tab within its window."},
"windowId": {"type": "integer", "minimum": 0, "description": "The ID of the window the tab is contained within."},
"selected": {"type": "boolean", "description": "Whether the tab is selected."},
+ "pinned": {"type": "boolean", "description": "Whether the tab is pinned."},
"url": {"type": "string", "description": "The URL the tab is displaying."},
"title": {"type": "string", "optional": true, "description": "The title of the tab. This may not be available if the tab is loading."},
"favIconUrl": {"type": "string", "optional": true, "description": "The URL of the tab's favicon. This may not be available if the tab is loading."},
@@ -871,7 +877,7 @@
],
"returns": {
"$ref": "Port",
- "description": "A port that can be used to communicate with the content scripts running in the specified tab."
+ "description": "A port that can be used to communicate with the content scripts running in the specified tab. The port's <a href='extension.html#type-Port'>onDisconnect</a> event is fired if the tab closes or does not exist. "
}
},
{
@@ -896,7 +902,7 @@
{
"name": "response",
"type": "any",
- "description": "The JSON response object sent by the handler of the request."
+ "description": "The JSON response object sent by the handler of the request. If an error occurs while connecting to the specified tab, the callback will be called with no arguments and <a href='extension.html#property-lastError'>chrome.extension.lastError</a> will be set to the error message."
}
]
}
@@ -974,6 +980,11 @@
"type": "boolean",
"optional": true,
"description": "Whether the tab should become the selected tab in the window. Defaults to <var>true</var>"
+ },
+ "pinned": {
+ "type": "boolean",
+ "optional": true,
+ "description": "Whether the tab should be pinned. Defaults to <var>false</var>"
}
}
},
@@ -1001,8 +1012,20 @@
"type": "object",
"name": "updateProperties",
"properties": {
- "url": {"type": "string", "optional": true},
- "selected": {"type": "boolean", "optional": true}
+ "url": {
+ "optional": true,
+ "description": "A URL to navigate the tab to."
+ },
+ "selected": {
+ "type": "boolean",
+ "optional": true,
+ "description": "Whether the tab should be selected."
+ },
+ "pinned": {
+ "type": "boolean",
+ "optional": true,
+ "description": "Whether the tab should be pinned."
+ }
}
},
{
@@ -1209,12 +1232,18 @@
"properties": {
"status": {
"type": "string",
+ "optional": true,
"description": "The status of the tab. Can be either <em>loading</em> or <em>complete</em>."
},
"url": {
"type": "string",
"optional": true,
- "description": "Only specified if the tab's URL changed."
+ "description": "The tab's URL if it has changed."
+ },
+ "pinned": {
+ "type": "boolean",
+ "optional": true,
+ "description": "The tab's new pinned state."
}
}
},
@@ -2665,12 +2694,12 @@
"properties": {
"menuItemId": {
"type": "integer",
- "description": "The id of the menu item that was clicked."
+ "description": "The ID of the menu item that was clicked."
},
"parentMenuItemId": {
"type": "integer",
"optional": true,
- "description": "The parent id, if any, for the item clicked."
+ "description": "The parent ID, if any, for the item clicked."
},
"mediaType": {
"type": "string",
@@ -2680,21 +2709,21 @@
"linkUrl": {
"type": "string",
"optional": true,
- "description": "If the element is a link, the url it points to."
+ "description": "If the element is a link, the URL it points to."
},
"srcUrl": {
"type": "string",
"optional": true,
- "description": "Will be present for elements with a 'src' url."
+ "description": "Will be present for elements with a 'src' URL."
},
"pageUrl": {
"type": "string",
- "description": "The url of the page where the menu item was clicked."
+ "description": "The URL of the page where the menu item was clicked."
},
"frameUrl": {
"type": "string",
"optional": true,
- "description": " The url of the frame of the element where the context menu was clicked, if it was in a frame."
+ "description": " The URL of the frame of the element where the context menu was clicked, if it was in a frame."
},
"selectionText": {
"type": "string",
@@ -2715,7 +2744,7 @@
"description": "Creates a new context menu item. Note that if an error occurs during creation, you may not find out until the creation callback fires (the details will be in chrome.extension.lastError).",
"returns": {
"type": "integer",
- "description": "The id of the newly created item."
+ "description": "The ID of the newly created item."
},
"parameters": [
{
@@ -2730,12 +2759,12 @@
"title": {
"type": "string",
"optional": "true",
- "description": "This must be specified unless type is 'separator'."
+ "description": "The text to be displayed in the item; this is <em>required</em> unless <em>type</em> is 'separator'. When the context is 'selection', you can use <code>%s</code> within the string to show the selected text. For example, if this parameter's value is \"Translate '%s' to Pig Latin\" and the user selects the word \"cool\", the context menu item for the selection is \"Translate 'cool' to Pig Latin\"."
},
"checked": {
"type": "boolean",
"optional": true,
- "description": "This only applies to the initial state of a checkbox or radio item. It indicates if the item should initially be checked/selected. Only one radio item can be selected at a time in a given group of radio items."
+ "description": "The initial state of a checkbox or radio item: true for selected and false for unselected. Only one radio item can be selected at a time in a given group of radio items."
},
"contexts": {
"type": "array",
@@ -2764,19 +2793,19 @@
"parentId": {
"type": "integer",
"optional": true,
- "description": "The id of a parent menu item - this makes the item a child of a previously added item."
+ "description": "The ID of a parent menu item; this makes the item a child of a previously added item."
},
"documentUrlPatterns": {
"type": "array",
"items": {"type": "string"},
"optional": true,
- "description": "Lets you restrict the item to only apply to documents whose URL matches one of the given patterns. (This applies to frames as well). For details on the format of a pattern, see <a href='match_patterns.html'>Match Patterns</a>."
+ "description": "Lets you restrict the item to apply only to documents whose URL matches one of the given patterns. (This applies to frames as well.) For details on the format of a pattern, see <a href='match_patterns.html'>Match Patterns</a>."
},
"targetUrlPatterns": {
"type": "array",
"items": {"type": "string"},
"optional": true,
- "description": "Similar to documentUrlPatterns, but this lets you filter based on the src attribute of img/audio/video tags and the href of anchor tags."
+ "description": "Similar to documentUrlPatterns, but lets you filter based on the src attribute of img/audio/video tags and the href of anchor tags."
}
}
},
@@ -2784,7 +2813,7 @@
"type": "function",
"name": "callback",
"optional": true,
- "description": "Called when the item has been created in the browser. If there were any problems creating the item, details will be avilable in chrome.extension.lastError.",
+ "description": "Called when the item has been created in the browser. If there were any problems creating the item, details will be available in chrome.extension.lastError.",
"parameters": []
}
]
@@ -2797,7 +2826,7 @@
{
"type": "integer",
"name": "id",
- "description": "The id of the item to update."
+ "description": "The ID of the item to update."
},
{
"type": "object",
@@ -2860,7 +2889,7 @@
{
"type": "integer",
"name": "menuItemId",
- "description": "The id of the context menu item to remove."
+ "description": "The ID of the context menu item to remove."
},
{
"type": "function",
@@ -4029,10 +4058,6 @@
"description": "Whether it is currently enabled or disabled.",
"type": "boolean"
},
- "enabled": {
- "description": "Whether it is currently enabled or disabled.",
- "type": "boolean"
- },
"isApp": {
"description": "True if this is an app.",
"type": "boolean"
@@ -4080,6 +4105,28 @@
]
},
{
+ "name": "get",
+ "description": "Return information about the installed extension with the given ID.",
+ "parameters": [
+ {
+ "name": "id",
+ "type": "string",
+ "description": "The ID from an item of $ref:ExtensionInfo."
+ },
+ {
+ "type": "function",
+ "name": "callback",
+ "optional": "true",
+ "parameters": [
+ {
+ "name": "result",
+ "$ref": "ExtensionInfo"
+ }
+ ]
+ }
+ ]
+ },
+ {
"name": "setEnabled",
"description": "Enable or disable an app or extension.",
"parameters": [
diff --git a/chrome/common/extensions/docs/a11y.html b/chrome/common/extensions/docs/a11y.html
index c8e2646..5c34cff 100644
--- a/chrome/common/extensions/docs/a11y.html
+++ b/chrome/common/extensions/docs/a11y.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Accessibility (a11y) - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/api_index.html b/chrome/common/extensions/docs/api_index.html
index 46ddd6e..299f041 100644
--- a/chrome/common/extensions/docs/api_index.html
+++ b/chrome/common/extensions/docs/api_index.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.* APIs - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/api_other.html b/chrome/common/extensions/docs/api_other.html
index c1ef26b..a4c11c6 100644
--- a/chrome/common/extensions/docs/api_other.html
+++ b/chrome/common/extensions/docs/api_other.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Other APIs - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -327,7 +331,7 @@ E.g. window.open(someUrl). --></dd>
<ul>
<li> audio
(<a href="http://www.html5rocks.com/tutorials/audio/quick/">tutorial</a>) </li>
- <li> app cache
+ <li> application cache
(<a href="http://www.html5rocks.com/tutorials/appcache/beginner/">tutorial</a>) </li>
<li> canvas </li>
<li> geolocation
diff --git a/chrome/common/extensions/docs/autoupdate.html b/chrome/common/extensions/docs/autoupdate.html
index f474abb..b8c8ea5 100644
--- a/chrome/common/extensions/docs/autoupdate.html
+++ b/chrome/common/extensions/docs/autoupdate.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Autoupdating - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/background_pages.html b/chrome/common/extensions/docs/background_pages.html
index 5227b51..e0760ef 100644
--- a/chrome/common/extensions/docs/background_pages.html
+++ b/chrome/common/extensions/docs/background_pages.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Background Pages - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/bookmarks.html b/chrome/common/extensions/docs/bookmarks.html
index 8283626..b906190 100644
--- a/chrome/common/extensions/docs/bookmarks.html
+++ b/chrome/common/extensions/docs/bookmarks.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Bookmarks - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/browserAction.html b/chrome/common/extensions/docs/browserAction.html
index 77c2b6c..4e00a55 100644
--- a/chrome/common/extensions/docs/browserAction.html
+++ b/chrome/common/extensions/docs/browserAction.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Browser Actions - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -473,7 +477,7 @@ in the <a href="#manifest">manifest</a>, or call the
Browser action icons should seem a little bigger
and heavier than page action icons.
</li><li><b>Don't</b> attempt to mimic
- Google Chrome's monochrome "wrench" and "page" icons.
+ Google Chrome's monochrome "wrench" icon.
That doesn't work well with themes, and anyway,
extensions should stand out a little.
</li><li><b>Do</b> use alpha transparency
diff --git a/chrome/common/extensions/docs/build/build.py b/chrome/common/extensions/docs/build/build.py
index 524e989..1ff2e0f 100755
--- a/chrome/common/extensions/docs/build/build.py
+++ b/chrome/common/extensions/docs/build/build.py
@@ -162,8 +162,14 @@ def main():
"build.sh script instead, which uses depot_tools python.")
parser = OptionParser()
- parser.add_option("--test-shell-path", dest="test_shell_path")
- parser.add_option("--page-name", dest="page_name")
+ parser.add_option("--test-shell-path", dest="test_shell_path",
+ metavar="PATH",
+ help="path to test_shell executable")
+ parser.add_option("--page-name", dest="page_name", metavar="PAGE",
+ help="only generate docs for PAGE.html")
+ parser.add_option("--nozip", dest="zips", action="store_false",
+ help="do not generate zip files for samples",
+ default=True)
(options, args) = parser.parse_args()
if (options.test_shell_path and os.path.isfile(options.test_shell_path)):
@@ -195,6 +201,11 @@ def main():
samples_manifest = SamplesManifest(_samples_dir, _base_dir, api_manifest)
samples_manifest.writeToFile(_samples_json)
+ # Write zipped versions of the samples listed in the manifest to the
+ # filesystem, unless the user has disabled it
+ if options.zips:
+ samples_manifest.writeZippedSamples()
+
modified_files = RenderPages(page_names, test_shell)
if (len(modified_files) == 0):
diff --git a/chrome/common/extensions/docs/build/directory.py b/chrome/common/extensions/docs/build/directory.py
index 312e5ac..79f5dd7 100644
--- a/chrome/common/extensions/docs/build/directory.py
+++ b/chrome/common/extensions/docs/build/directory.py
@@ -221,16 +221,11 @@ class SamplesManifest(object):
def writeToFile(self, path):
""" Writes the contents of this manifest file as a JSON-encoded text file.
- For each sample written to the manifest, create a zip file with the sample
- contents in the sample's parent directory.
Args:
path: The path to write the samples manifest file to.
"""
- for sample in self._manifest_data['samples']:
- sample.write_zip()
-
manifest_text = json.dumps(self._manifest_data, indent=2)
output_path = os.path.realpath(path)
try:
@@ -241,6 +236,13 @@ class SamplesManifest(object):
output_file.write(manifest_text)
output_file.close()
+ def writeZippedSamples(self):
+ """ For each sample in the current manifest, create a zip file with the
+ sample contents in the sample's parent directory. """
+
+ for sample in self._manifest_data['samples']:
+ sample.write_zip()
+
class Sample(dict):
""" Represents metadata about a Chrome extension sample.
@@ -275,6 +277,7 @@ class Sample(dict):
self['search_string'] = self._get_search_string()
self['source_files'] = self._parse_source_files()
self['id'] = hashlib.sha1(self['path']).hexdigest()
+ self['zip_path'] = self._get_relative_zip_path()
_FEATURE_ATTRIBUTES = (
'browser_action',
@@ -371,6 +374,19 @@ class Sample(dict):
return real_manifest_path.replace(real_base_path, '')\
.replace('manifest.json', '')[1:]
+ def _get_relative_zip_path(self):
+ """ Returns a relative path from the base dir to the sample's zip file.
+
+ Intended for locating the zip file for the sample in the samples manifest.
+
+ Returns:
+ A relative directory path form the sample manifest's directory to this
+ sample's zip file.
+ """
+ zip_filename = self._get_zip_filename()
+ zip_relpath = os.path.dirname(os.path.dirname(self._get_relative_path()))
+ return os.path.join(zip_relpath, zip_filename)
+
def _get_search_string(self):
""" Constructs a string to be used when searching the samples list.
@@ -394,6 +410,17 @@ class Sample(dict):
.upper()
return search_string
+ def _get_zip_filename(self):
+ """ Returns the filename to be used for a generated zip of the sample.
+
+ Returns:
+ A string in the form of "<dirname>.zip" where <dirname> is the name
+ of the directory containing this sample's manifest.json.
+ """
+ sample_path = os.path.realpath(os.path.dirname(self._manifest_path))
+ sample_dirname = os.path.basename(sample_path)
+ return "%s.zip" % sample_dirname
+
def _parse_api_calls(self, api_methods):
""" Returns a list of Chrome extension API calls the sample makes.
@@ -589,7 +616,7 @@ class Sample(dict):
sample_dirname = os.path.basename(sample_path)
sample_parentpath = os.path.dirname(sample_path)
- zip_filename = "%s.zip" % sample_dirname
+ zip_filename = self._get_zip_filename()
zip_path = os.path.join(sample_parentpath, zip_filename)
zip_file = zipfile.ZipFile(zip_path, 'w')
@@ -603,11 +630,6 @@ class Sample(dict):
# Relative path to store the file in under the zip.
relpath = sample_dirname + abspath.replace(sample_path, "")
zip_file.write(abspath, relpath)
-
- self['zip_path'] = os.path.join(
- os.path.dirname(os.path.dirname(self._get_relative_path())),
- zip_filename)
-
except RuntimeError, msg:
raise Exception("Could not write zip at " % zip_path)
finally:
diff --git a/chrome/common/extensions/docs/content_scripts.html b/chrome/common/extensions/docs/content_scripts.html
index 4a5352e..c2845b8 100644
--- a/chrome/common/extensions/docs/content_scripts.html
+++ b/chrome/common/extensions/docs/content_scripts.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Content Scripts - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/contextMenus.html b/chrome/common/extensions/docs/contextMenus.html
index a7b2cdb..6f055fd 100644
--- a/chrome/common/extensions/docs/contextMenus.html
+++ b/chrome/common/extensions/docs/contextMenus.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Context Menus - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -537,7 +541,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>This must be specified unless type is 'separator'.</dd>
+ <dd>The text to be displayed in the item; this is <em>required</em> unless <em>type</em> is 'separator'. When the context is 'selection', you can use <code>%s</code> within the string to show the selected text. For example, if this parameter's value is "Translate '%s' to Pig Latin" and the user selects the word "cool", the context menu item for the selection is "Translate 'cool' to Pig Latin".</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -595,7 +599,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>This only applies to the initial state of a checkbox or radio item. It indicates if the item should initially be checked/selected. Only one radio item can be selected at a time in a given group of radio items.</dd>
+ <dd>The initial state of a checkbox or radio item: true for selected and false for unselected. Only one radio item can be selected at a time in a given group of radio items.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -865,7 +869,7 @@ You can find samples of this API on the
</div>
</div>
- </dl>
+ </dl>
</div>
</dd>
@@ -901,7 +905,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The id of a parent menu item - this makes the item a child of a previously added item.</dd>
+ <dd>The ID of a parent menu item; this makes the item a child of a previously added item.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -970,7 +974,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Lets you restrict the item to only apply to documents whose URL matches one of the given patterns. (This applies to frames as well). For details on the format of a pattern, see <a href="match_patterns.html">Match Patterns</a>.</dd>
+ <dd>Lets you restrict the item to apply only to documents whose URL matches one of the given patterns. (This applies to frames as well.) For details on the format of a pattern, see <a href="match_patterns.html">Match Patterns</a>.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1039,7 +1043,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Similar to documentUrlPatterns, but this lets you filter based on the src attribute of img/audio/video tags and the href of anchor tags.</dd>
+ <dd>Similar to documentUrlPatterns, but lets you filter based on the src attribute of img/audio/video tags and the href of anchor tags.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1107,7 +1111,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Called when the item has been created in the browser. If there were any problems creating the item, details will be avilable in chrome.extension.lastError.</dd>
+ <dd>Called when the item has been created in the browser. If there were any problems creating the item, details will be available in chrome.extension.lastError.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1171,7 +1175,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The id of the newly created item.</dd>
+ <dd>The ID of the newly created item.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1282,7 +1286,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The id of the context menu item to remove.</dd>
+ <dd>The ID of the context menu item to remove.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1580,7 +1584,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The id of the item to update.</dd>
+ <dd>The ID of the item to update.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2401,7 +2405,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The id of the menu item that was clicked.</dd>
+ <dd>The ID of the menu item that was clicked.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2459,7 +2463,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The parent id, if any, for the item clicked.</dd>
+ <dd>The parent ID, if any, for the item clicked.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2575,7 +2579,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>If the element is a link, the url it points to.</dd>
+ <dd>If the element is a link, the URL it points to.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2633,7 +2637,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Will be present for elements with a 'src' url.</dd>
+ <dd>Will be present for elements with a 'src' URL.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2691,7 +2695,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The url of the page where the menu item was clicked.</dd>
+ <dd>The URL of the page where the menu item was clicked.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -2749,7 +2753,7 @@ You can find samples of this API on the
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd> The url of the frame of the element where the context menu was clicked, if it was in a frame.</dd>
+ <dd> The URL of the frame of the element where the context menu was clicked, if it was in a frame.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
diff --git a/chrome/common/extensions/docs/cookies.html b/chrome/common/extensions/docs/cookies.html
index ea79e4c..482a342 100644
--- a/chrome/common/extensions/docs/cookies.html
+++ b/chrome/common/extensions/docs/cookies.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Cookies - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/crx.html b/chrome/common/extensions/docs/crx.html
index 9cd28ff..22ad2b5 100644
--- a/chrome/common/extensions/docs/crx.html
+++ b/chrome/common/extensions/docs/crx.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>CRX Package Format - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/css/ApiRefStyles.css b/chrome/common/extensions/docs/css/ApiRefStyles.css
index b3b86f3..ebc8669 100644
--- a/chrome/common/extensions/docs/css/ApiRefStyles.css
+++ b/chrome/common/extensions/docs/css/ApiRefStyles.css
@@ -800,6 +800,29 @@ a.leftNavSelected,.leftNavSelected a,a.leftNavSelected:visited,.leftNavSelected
background:#fff
}
+#gc-toc .toggle {
+ background: url('../images/toggle_sprite.png') no-repeat 0px 0px;
+ width: 9px;
+ height: 9px;
+ overflow: hidden;
+ float: left;
+ text-decoration: none;
+ margin: 4px 1px 4px -13px;
+ cursor: pointer;
+}
+
+#gc-toc .toggle.selected {
+ background-position: 0 -9px;
+}
+
+#gc-toc .toggle:hover {
+ background-position: 0 -18px;
+}
+
+#gc-toc .toggle.selected:hover {
+ background-position: 0 -27px;
+}
+
#toc h2 {
font-weight:bold;
font-size:100%;
diff --git a/chrome/common/extensions/docs/devguide.html b/chrome/common/extensions/docs/devguide.html
index 298996e..2669a04 100644
--- a/chrome/common/extensions/docs/devguide.html
+++ b/chrome/common/extensions/docs/devguide.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Developer's Guide - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/docs.html b/chrome/common/extensions/docs/docs.html
index 2a81648..685f6aa 100644
--- a/chrome/common/extensions/docs/docs.html
+++ b/chrome/common/extensions/docs/docs.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Hello There! - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/events.html b/chrome/common/extensions/docs/events.html
index 7fbf71e..be42e7b 100644
--- a/chrome/common/extensions/docs/events.html
+++ b/chrome/common/extensions/docs/events.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Events - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/extension-docs.zip b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs.zip
new file mode 100644
index 0000000..7e81cea
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/background.html b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/background.html
new file mode 100644
index 0000000..19fcc45
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/background.html
@@ -0,0 +1,466 @@
+<!DOCTYPE html>
+<!--
+ * 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.
+-->
+<html>
+ <head>
+ </head>
+ <body>
+ <script>
+ /**
+ * Allows for binding callbacks to a specific scope.
+ * @param {Object} scope Scope to bind to.
+ * @returns {Function} A wrapped call to this function.
+ */
+ Function.prototype.bind = function(scope) {
+ var func = this;
+ return function() {
+ return func.apply(scope, arguments);
+ };
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Holds the search index and exposes operations to search the API docs.
+ * @constructor
+ */
+ function APISearchCorpus() {
+ this.corpus_ = [];
+ };
+
+ /**
+ * Adds an entry to the index.
+ * @param {String} name Name of the function (e.g. chrome.tabs.get).
+ * @param {String} url Url to the documentation.
+ * @param {String} desc Description (optional).
+ * @param {String} type The type of entry (e.g. method, event).
+ */
+ APISearchCorpus.prototype.addEntry = function(name, url, desc, type) {
+ this.corpus_.push({
+ 'name' : name,
+ 'url' : url,
+ 'ranges' : [],
+ 'description' : desc,
+ 'type' : type
+ });
+ };
+
+ /**
+ * Locates a match from the supplied keywords against text.
+ *
+ * Keywords are matched in the order supplied, and a non-overlapping
+ * search is used. The ranges are returned in a way that is easily
+ * converted to the style array required by the omnibox API.
+ *
+ * @param {Array.<String>} keywords A list of keywords to check.
+ * @param {String} name The name to search against.
+ * @returns {Array.<Array.<number>>|null} A list of indexes corresponding
+ * to matches, or null if no match was found.
+ */
+ APISearchCorpus.prototype.findMatch_ = function(keywords, name) {
+ var ranges = [];
+ var indexFrom = 0;
+ for (var i = 0; i < keywords.length; i++) {
+ var keyword = keywords[i].toLowerCase();
+ var start = name.indexOf(keyword, indexFrom);
+ if (start == -1) {
+ return null;
+ }
+ var end = start + keyword.length;
+ ranges.push([start, end]);
+ indexFrom = end + 1;
+ }
+ return ranges;
+ };
+
+ /**
+ * Searches this corpus for the supplied text.
+ * @param {String} text Query text.
+ * @param {Number} limit Max results to return.
+ * @returns {Array.<Object>} A list of entries corresponding with
+ * matches (@see APISearchCorpus.findMatch_ for keyword search
+ * algorithm. Results are returned in a sorted order, first by
+ * length, then alphabetically by name. An exact match will be
+ * returned first.
+ */
+ APISearchCorpus.prototype.search = function(text, limit) {
+ var results = [];
+ var match = null;
+ if (!text || text.length == 0) {
+ return this.corpus_.slice(0, limit); // No text, start listing APIs.
+ }
+ var searchText = text.toLowerCase();
+ var keywords = searchText.split(' ');
+ for (var i = 0; i < this.corpus_.length; i++) {
+ var name = this.corpus_[i]['name'].toLowerCase();
+ if (results.length < limit) {
+ var result = this.findMatch_(keywords, name);
+ if (result) {
+ this.corpus_[i]['ranges'] = result;
+ results.push(this.corpus_[i]);
+ }
+ }
+ if (!match && searchText == name) {
+ match = this.corpus_[i]; // An exact match.
+ }
+ if (match && results.length >= limit) {
+ break; // Have an exact match and have reached the search limit.
+ }
+ }
+ if (match) {
+ results.unshift(match); // Add any exact match to the front.
+ }
+ return results;
+ };
+
+ /**
+ * Sorts the corpus according to name length, then name alphabetically.
+ */
+ APISearchCorpus.prototype.sort = function() {
+ function compareLength(a, b) {
+ return a['name'].length - b['name'].length;
+ };
+
+ function compareAlpha(a, b) {
+ if (a['name'] < b['name']) return -1;
+ if (a['name'] > b['name']) return 1;
+ return 0;
+ };
+
+ function compare(a, b) {
+ var result = compareLength(a, b);
+ if (result == 0) result = compareAlpha(a, b);
+ return result;
+ };
+
+ this.corpus_.sort(compare);
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Provides an interface to the Chrome Extensions documentation site.
+ * @param {APISearchCorpus} corpus The search corpus to populate.
+ * @constructor
+ */
+ function DocsManager(corpus) {
+ this.CODE_URL_PREFIX = 'http://code.google.com/chrome/extensions/';
+ this.API_MANIFEST_URL = [
+ 'http://src.chromium.org/viewvc/chrome/trunk/src/',
+ 'chrome/common/extensions/api/extension_api.json'
+ ].join('');
+ this.corpus_ = corpus;
+ };
+
+ /**
+ * Initiates a fetch of the docs and populates the corpus.
+ */
+ DocsManager.prototype.fetch = function() {
+ this.fetchApi_(this.onApi_.bind(this));
+ };
+
+ /**
+ * Retrieves the API manifest from cache or fetches a new one if none.
+ * @param {Function} callback The function to pass the parsed manifest
+ * data to.
+ */
+ DocsManager.prototype.fetchApi_ = function(callback) {
+ var currentCacheTime = this.getCacheTime_();
+ if (localStorage['cache-time'] && localStorage['cache']) {
+ var cacheTime = JSON.parse(localStorage['cache-time']);
+ if (cacheTime < currentCacheTime) {
+ callback(JSON.parse(localStorage['cache']));
+ return;
+ }
+ }
+ var xhr = new XMLHttpRequest();
+ xhr.addEventListener('readystatechange', function(evt) {
+ if (xhr.readyState == 4 && xhr.responseText) {
+ localStorage['cache-time'] = JSON.stringify(currentCacheTime);
+ localStorage['cache'] = xhr.responseText;
+ var json = JSON.parse(xhr.responseText);
+ callback(json);
+ }
+ });
+ xhr.open('GET', this.API_MANIFEST_URL, true);
+ xhr.send();
+ };
+
+ /**
+ * Returns a time which can be used to cache a manifest response.
+ * @returns {Number} A timestamp divided by the number of ms in a day,
+ * rounded to the nearest integer. This means the number should
+ * change only once per day, invalidating the cache that often.
+ */
+ DocsManager.prototype.getCacheTime_ = function() {
+ var time = new Date().getTime();
+ time = Math.round(time / (1000 * 60 * 60 * 24));
+ return time;
+ };
+
+ /**
+ * Returns an URL for the documentation given an API element.
+ * @param {String} namespace The namespace (e.g. tabs, windows).
+ * @param {String} type The type of element (e.g. event, method, type).
+ * @param {String} name The name of the element (e.g. onRemoved).
+ * @returns {String} An URL corresponding with the documentation for the
+ * given element.
+ */
+ DocsManager.prototype.getDocLink_ = function(namespace, type, name) {
+ var linkparts = [ this.CODE_URL_PREFIX, namespace, '.html' ];
+ if (type && name) {
+ linkparts.push('#', type, '-', name);
+ }
+ return linkparts.join('');
+ };
+
+ /**
+ * Returns a qualified name for an API element.
+ * @param {String} namespace The namespace (e.g. tabs, windows).
+ * @param {String} name The name of the element (e.g. onRemoved).
+ * @returns {String} A qualified API name (e.g. chrome.tabs.onRemoved).
+ */
+ DocsManager.prototype.getName_ = function(namespace, name) {
+ var nameparts = [ 'chrome', namespace ];
+ if (name) {
+ nameparts.push(name);
+ }
+ return nameparts.join('.');
+ };
+
+ /**
+ * Parses an API manifest data structure and populates the search index.
+ * @param {Object} api The api manifest, as a JSON-parsed object.
+ */
+ DocsManager.prototype.onApi_ = function(api) {
+ for (var i = 0; i < api.length; i++) {
+ var module = api[i];
+ if (module.nodoc) {
+ continue;
+ }
+ var ns = module.namespace;
+ var nsName = this.getName_(ns);
+ var nsUrl = this.getDocLink_(ns);
+ this.corpus_.addEntry(nsName, nsUrl, null, 'namespace');
+ this.parseAPIArray_('method', ns, module.functions);
+ this.parseAPIArray_('event', ns, module.events);
+ this.parseAPIArray_('type', ns, module.types);
+ this.parseAPIObject_('property', ns, module.properties);
+ this.corpus_.sort();
+ }
+ };
+
+ /**
+ * Parses an API manifest subsection which is formatted as an Array.
+ * @param {String} type The type of data (e.g. method, event, type).
+ * @param {String} ns The namespace (e.g. tabs, windows).
+ * @param {Array} list The list of API elements.
+ */
+ DocsManager.prototype.parseAPIArray_ = function(type, ns, list) {
+ if (!list) return;
+ for (var j = 0; j < list.length; j++) {
+ var item = list[j];
+ if (item.nodoc) continue;
+ var name = item.name || item.id;
+ var fullname = this.getName_(ns, name);
+ var url = this.getDocLink_(ns, type, name);
+ var description = item.description;
+ this.corpus_.addEntry(fullname, url, description, type);
+ }
+ };
+
+ /**
+ * Parses an API manifest subsection which is formatted as an Object.
+ * @param {String} type The type of data (e.g. property).
+ * @param {String} ns The namespace (e.g. tabs, windows).
+ * @param {Object} list The object containing API elements.
+ */
+ DocsManager.prototype.parseAPIObject_ = function(type, ns, list) {
+ for (var prop in list) {
+ if (list.hasOwnProperty(prop)) {
+ var name = this.getName_(ns, prop);
+ var url = this.getDocLink_(ns, type, prop);
+ var description = list[prop].description;
+ this.corpus_.addEntry(name, url, description, type);
+ }
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Manages text input into the omnibox and returns search results.
+ * @param {APISearchCorpus} Populated search corpus.
+ * @param {TabManager} Manager to use to open tabs.
+ * @constructor
+ */
+ function OmniboxManager(corpus, tabManager) {
+ this.SEPARATOR = ' - ';
+ this.corpus_ = corpus;
+ this.tabManager_ = tabManager;
+ chrome.experimental.omnibox.onInputChanged.addListener(
+ this.onChanged_.bind(this));
+ chrome.experimental.omnibox.onInputEntered.addListener(
+ this.onEntered_.bind(this));
+ };
+
+ /**
+ * Converts a corpus match to an object suitable for the omnibox API.
+ * @param {Object} match The match to convert.
+ * @returns {Object} A suggestion object formatted for the omnibox API.
+ */
+ OmniboxManager.prototype.matchToSuggestion_ = function(match) {
+ var styles = [ ];
+ var ranges = match['ranges'];
+ var desc = match['name'];
+ var name = match['name'];
+ var lastIndex = 0;
+ for (var i = 0; i < ranges.length; i++) {
+ styles.push(chrome.experimental.omnibox.styleMatch(ranges[i][0]));
+ styles.push(chrome.experimental.omnibox.styleNone(ranges[i][1]));
+ lastIndex = ranges[i][1];
+ }
+
+ if (match['type']) {
+ // Abusing the URL style a little, but want this to stand out.
+ desc = this.pushStyle_(styles, 'Url', desc, match['type']);
+ lastIndex = desc.length;
+ }
+ if (match['description']) {
+ desc = this.pushStyle_(styles, 'Dim', desc, match['description']);
+ lastIndex = desc.length;
+ }
+
+ if (lastIndex == desc.length) styles.pop();
+
+ return {
+ 'content' : name,
+ 'description' : desc,
+ 'descriptionStyles' : styles
+ };
+ };
+
+ /**
+ * Suggests a list of possible matches when omnibox text changes.
+ * @param {String} text Text input from the omnibox.
+ * @param {Function} suggest Callback to execute with a list of
+ * suggestion objects, if any matches were found.
+ */
+ OmniboxManager.prototype.onChanged_ = function(text, suggest) {
+ var matches = this.corpus_.search(text, 10);
+ var suggestions = [];
+ for (var i = 0; i < matches.length; i++) {
+ var suggestion = this.matchToSuggestion_(matches[i]);
+ suggestions.push(suggestion);
+ }
+ suggest(suggestions);
+ };
+
+ /**
+ * Opens the most appropriate URL when enter is pressed in the omnibox.
+ *
+ * Note that the entered text does not have to be exact - the first
+ * search result is automatically opened when enter is pressed.
+ *
+ * @param {String} text The text entered.
+ */
+ OmniboxManager.prototype.onEntered_ = function(text) {
+ var matches = this.corpus_.search(text, 1);
+ if (matches.length > 0) {
+ this.tabManager_.open(matches[0]['url']);
+ }
+ };
+
+ /**
+ * Helper function for constructing a suggestion style list.
+ *
+ * Adds a separator and text to a description, and modifies an array
+ * of styles so that the separator is not styled and the additional text
+ * obtains the requested style type.
+ *
+ * This method expects the list of styles to end with a styleNone style.
+ * It will modify the list so that the last element is a styleNone style.
+ * The last element will always be at the end of the returned string,
+ * which will throw an error unless it is removed before being passed
+ * to the API (this method is intended to be called a few times in a row).
+ * @see OmniboxManager.matchToSuggestion_ for code that removes this last
+ * entry.
+ *
+ * @param {Array.<Object>} styles An array of styles, in the format
+ * expected by the omnibox API.
+ * @param {String} type The style type to apply - must be one of
+ * "Dim", "Match", "None", and "Url".
+ * @param {String} desc The description text to append to and style.
+ * @param {String} text The text to append to the description.
+ * @returns {String} The description plus a separator and the supplied
+ * text, intended to overwrite the variable which was passed into
+ * this function as "desc".
+ */
+ OmniboxManager.prototype.pushStyle_ = function(styles, type, desc, text) {
+ desc += this.SEPARATOR;
+ styles.push(chrome.experimental.omnibox['style' + type](desc.length));
+ desc += text;
+ styles.push(chrome.experimental.omnibox.styleNone(desc.length));
+ return desc;
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Manages opening urls in tabs.
+ * @constructor
+ */
+ function TabManager() {
+ this.tab_ = null;
+ chrome.tabs.onRemoved.addListener(this.onRemoved_.bind(this));
+ };
+
+ /**
+ * When a tab is removed, see if it was opened by us and null out if yes.
+ * @param {Number} tabid ID of the removed tab.
+ */
+ TabManager.prototype.onRemoved_ = function(tabid) {
+ if (this.tab_ && tabid == this.tab_.id) this.tab_ = null;
+ };
+
+ /**
+ * When a tab opened by us is created, store it for future updates.
+ * @param {Tab} tab The tab which was just opened.
+ */
+ TabManager.prototype.onTab_ = function(tab) {
+ this.tab_ = tab;
+ };
+
+ /**
+ * Opens the supplied URL.
+ *
+ * The first time this method is called a new tab is created. Subsequent
+ * times this is called, the opened tab will be updated. If that tab
+ * is ever closed, then a new tab will be created for the next call.
+ *
+ * @param {String} url The URL to open.
+ */
+ TabManager.prototype.open = function(url) {
+ if (url) {
+ var args = { 'url' : url, 'selected' : true };
+ if (this.tab_) {
+ chrome.tabs.update(this.tab_.id, args);
+ } else {
+ chrome.tabs.create(args, this.onTab_.bind(this));
+ }
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+
+ var corpus = new APISearchCorpus();
+ var docsManager = new DocsManager(corpus);
+ docsManager.fetch();
+ var tabManager = new TabManager();
+ var omnibox = new OmniboxManager(corpus, tabManager);
+ </script>
+ </body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/icon-128.png b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/icon-128.png
new file mode 100644
index 0000000..c7e114f
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/icon-128.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/icon-16.png b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/icon-16.png
new file mode 100644
index 0000000..23b34a0
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/icon-16.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/manifest.json b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/manifest.json
new file mode 100644
index 0000000..8e6b3b9
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/manifest.json
@@ -0,0 +1,16 @@
+{
+ "name" : "Extension Docs Search",
+ "description" : "Search the Chrome Extensions documentation. To use, type 'crdoc' plus a search term into the Omnibox.",
+ "version" : "1.0.0",
+ "permissions" : [
+ "experimental",
+ "http://src.chromium.org/viewvc/*",
+ "tabs"
+ ],
+ "icons" : {
+ "16" : "icon-16.png",
+ "128" : "icon-128.png"
+ },
+ "omnibox_keyword" : "crdoc",
+ "background_page" : "background.html"
+}
diff --git a/chrome/common/extensions/docs/examples/api/omnibox.zip b/chrome/common/extensions/docs/examples/api/omnibox/simple-example.zip
index 58ba199..532eb00 100644
--- a/chrome/common/extensions/docs/examples/api/omnibox.zip
+++ b/chrome/common/extensions/docs/examples/api/omnibox/simple-example.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/background.html b/chrome/common/extensions/docs/examples/api/omnibox/simple-example/background.html
index ff83ff2..ff83ff2 100644
--- a/chrome/common/extensions/docs/examples/api/omnibox/background.html
+++ b/chrome/common/extensions/docs/examples/api/omnibox/simple-example/background.html
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/manifest.json b/chrome/common/extensions/docs/examples/api/omnibox/simple-example/manifest.json
index 2b63ca2..c48a345 100644
--- a/chrome/common/extensions/docs/examples/api/omnibox/manifest.json
+++ b/chrome/common/extensions/docs/examples/api/omnibox/simple-example/manifest.json
@@ -1,5 +1,6 @@
{
"name": "Omnibox Example",
+ "description" : "To use, type 'omnix' plus a search term into the Omnibox.",
"version": "1.0",
"permissions": [ "experimental" ],
"background_page": "background.html",
diff --git a/chrome/common/extensions/docs/examples/api/processes/process_monitor.zip b/chrome/common/extensions/docs/examples/api/processes/process_monitor.zip
new file mode 100644
index 0000000..60d5641
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/processes/process_monitor.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs.zip b/chrome/common/extensions/docs/examples/api/processes/show_tabs.zip
index 770b435..ba3c761 100644
--- a/chrome/common/extensions/docs/examples/api/processes/show_tabs.zip
+++ b/chrome/common/extensions/docs/examples/api/processes/show_tabs.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark.zip b/chrome/common/extensions/docs/examples/extensions/benchmark.zip
index af258d4..7f43bdb 100644
--- a/chrome/common/extensions/docs/examples/extensions/benchmark.zip
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/README.txt b/chrome/common/extensions/docs/examples/extensions/benchmark/README.txt
index 8136ab3..2267580 100644
--- a/chrome/common/extensions/docs/examples/extensions/benchmark/README.txt
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/README.txt
@@ -14,5 +14,14 @@ To use this benchmark, you'll need to run chrome with the the
the benchmark can clear idle connections and the cache.
The code found in the jst/ subdirectory is JSTemplate code from
-http://code.google.com/p/google-jstemplate/
+http://code.google.com/p/google-jstemplate/.
+
+In jquery/, jquery-1.4.2.min.js is from http://jquery.com/. jquery.flot.min.js
+is a plotting library and from http://code.google.com/p/flot/.
+jquery.flot.dashes.js is an enhancement of Flot for dashed lines and from
+http://code.google.com/p/flot/issues/detail?id=61.
+
+In util/, sortable.js serves for sorting table content and is from
+http://www.kryogenix.org/code/browser/sorttable/. table2CSV.js is for exporting
+table data to .csv and from http://www.kunalbabre.com/projects/table2CSV.php.
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/background.html b/chrome/common/extensions/docs/examples/extensions/benchmark/background.html
index ca712ff..36e4c31 100644
--- a/chrome/common/extensions/docs/examples/extensions/benchmark/background.html
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/background.html
@@ -163,19 +163,22 @@ function Benchmark() {
current_ = {};
current_.url = url;
+ current_.timestamp = new Date();
current_.viaSpdy = false;
current_.startLoadResults = new Array(); // times to start
current_.commitLoadResults = new Array(); // times to commit
current_.docLoadResults = new Array(); // times to docload
current_.paintResults = new Array(); // times to paint
current_.totalResults = new Array(); // times to complete load
- current_.bytesRead = 0;
- current_.bytesWritten = 0;
+ current_.KbytesRead = new Array();
+ current_.KbytesWritten = new Array();
+ current_.readbpsResults = new Array();
+ current_.writebpsResults = new Array();
current_.totalTime = 0;
current_.iterations = 0;
- current_.requests = 0;
- current_.connects = 0;
- current_.spdySessions = 0;
+ current_.requests = new Array();
+ current_.connects = new Array();
+ current_.spdySessions = new Array();
current_.domNum = 0;
current_.maxDepth = 0;
current_.minDepth = 0;
@@ -237,7 +240,7 @@ function Benchmark() {
this.openNextPage = function() {
var benchmark = nextBenchmark();
benchmark.pageStart();
- chrome.tabs.create({"url": benchmark.url(),"selected": false},
+ chrome.tabs.create({"url": benchmark.url(),"selected": true},
function(tab) {
benchmarkWindow = tab;
// script.js only executes on tested pages
@@ -297,6 +300,43 @@ function Benchmark() {
// Called when a page finishes loading.
this.pageFinished = function(load_times, domNum, depths) {
+
+ // Make sure the content can be fetched via spdy if it is enabled.
+ if (window.enableSpdy && !load_times.wasFetchedViaSpdy) {
+ alert("Can not fetch current url via spdy.\n" +
+ "Ending current test.");
+ me_.finish();
+ // Move on to next benchmarked pages.
+ if (benchmarks.length > 0) {
+ if (window.clearConnections) {
+ chrome.benchmarking.closeConnections();
+ }
+ setTimeout(me_.runPage, 100);
+ }
+ return;
+ }
+
+ // If last fetch was via spdy, current fetch should use spdy too. Same
+ // for vise versa.
+ if (current_.iterations > 0 &&
+ current_.viaSpdy != load_times.wasFetchedViaSpdy) {
+ alert("Error: viaSpdy for current fetch is different from last fetch!\n" +
+ "Ending current test.");
+ // Current data set is invalid: remove from the result array.
+ var currIndex;
+ currIndex = window.results.data.indexOf(current_, 0);
+ window.results.data.splice(currIndex, 1);
+ me_.displayResults();
+ me_.finish();
+ if (benchmarks.length > 0) {
+ if (window.clearConnections) {
+ chrome.benchmarking.closeConnections();
+ }
+ setTimeout(me_.runPage, 100);
+ }
+ return;
+ }
+
var requested = load_times.requestTime;
var started = load_times.startLoadTime;
var startLoadTime =
@@ -326,22 +366,6 @@ function Benchmark() {
totalTime_ += totalTime;
count_++;
- // Make sure the content can be fetched via spdy if it is enabled.
- if (window.enableSpdy && !load_times.wasFetchedViaSpdy) {
- alert("Can not fetch current url via spdy.\n" +
- "Ending current test.");
- runCount_ = 1;
- }
-
- // If last fetch was via spdy, current fetch should use spdy too. Same
- // for vise versa.
- if (current_.iterations > 0 &&
- current_.viaSpdy != load_times.wasFetchedViaSpdy) {
- alert("Error: viaSpdy for current fetch is different from last fetch!\n" +
- "Ending current test.");
- runCount_ = 1;
- }
-
// Get the index of current benchmarked page in the result array.
var currIndex;
currIndex = window.results.data.indexOf(current_, 0);
@@ -354,16 +378,20 @@ function Benchmark() {
current_.docLoadResults.push(docLoadTime);
current_.paintResults.push(paintTime);
current_.totalResults.push(totalTime);
- current_.bytesRead += chrome.benchmarking.counter(kTCPReadBytes) -
- initialReadBytes_;
- current_.bytesWritten += chrome.benchmarking.counter(kTCPWriteBytes) -
- initialWriteBytes_;
- current_.requests += chrome.benchmarking.counter(kRequestCount) -
- initialRequestCount_;
- current_.connects += chrome.benchmarking.counter(kConnectCount) -
- initialConnectCount_;
- current_.spdySessions += chrome.benchmarking.counter(kSpdySessionCount) -
- initialSpdySessionCount_;
+ var bytesRead = chrome.benchmarking.counter(kTCPReadBytes) -
+ initialReadBytes_;
+ var bytesWrite = chrome.benchmarking.counter(kTCPWriteBytes) -
+ initialWriteBytes_;
+ current_.KbytesRead.push(bytesRead / 1024);
+ current_.KbytesWritten.push(bytesWrite / 1024);
+ current_.readbpsResults.push(bytesRead * 8 / totalTime);
+ current_.writebpsResults.push(bytesWrite * 8 / totalTime);
+ current_.requests.push(chrome.benchmarking.counter(kRequestCount) -
+ initialRequestCount_);
+ current_.connects.push(chrome.benchmarking.counter(kConnectCount) -
+ initialConnectCount_);
+ current_.spdySessions.push(chrome.benchmarking.counter(kSpdySessionCount) -
+ initialSpdySessionCount_);
current_.totalTime += totalTime;
current_.domNum = domNum;
current_.maxDepth = depths[0];
@@ -374,7 +402,7 @@ function Benchmark() {
if (currIndex == -1) {
window.results.data.push(current_);
} else {
- window.results.data[currIndex]=current_;
+ window.results.data[currIndex] = current_;
}
if (--runCount_ == 0) {
@@ -386,7 +414,6 @@ function Benchmark() {
if (window.clearConnections) {
chrome.benchmarking.closeConnections();
}
-
setTimeout(me_.runPage, 100);
}
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-1.4.2.min.js b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-1.4.2.min.js
new file mode 100644
index 0000000..7c24308
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-1.4.2.min.js
@@ -0,0 +1,154 @@
+/*!
+ * jQuery JavaScript Library v1.4.2
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
+ */
+(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
+"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
+function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
+L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
+"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
+true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
+s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
+else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
+a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
+w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
+" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
+if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
+"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
+a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
+isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
+if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
+function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
+if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
+g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
+for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
+relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
+h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
+CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
+h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
+!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
+if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
+function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
+{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
+a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
+""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
+return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
+Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
+"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
+serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
+function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
+"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
+false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
+d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
+this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
+this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
+function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
+this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
+c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
+f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-ui-1.8.4.custom.min.js b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-ui-1.8.4.custom.min.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-ui-1.8.4.custom.min.js
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.client.js b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.client.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.client.js
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.dashes.js b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.dashes.js
new file mode 100644
index 0000000..7cebc92
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.dashes.js
@@ -0,0 +1,237 @@
+/*
+ * jQuery.flot.dashes
+ *
+ * options = {
+ * series: {
+ * dashes: {
+ *
+ * // show
+ * // default: false
+ * // Whether to show dashes for the series.
+ * show: <boolean>,
+ *
+ * // lineWidth
+ * // default: 2
+ * // The width of the dashed line in pixels.
+ * lineWidth: <number>,
+ *
+ * // dashLength
+ * // default: 10
+ * // Controls the length of the individual dashes and the amount of
+ * // space between them.
+ * // If this is a number, the dashes and spaces will have that length.
+ * // If this is an array, it is read as [ dashLength, spaceLength ]
+ * dashLength: <number> or <array[2]>
+ * }
+ * }
+ * }
+ */
+(function($){
+
+ function init(plot) {
+
+ plot.hooks.processDatapoints.push(function(plot, series, datapoints) {
+
+ if (!series.dashes.show) return;
+
+ plot.hooks.draw.push(function(plot, ctx) {
+
+ var plotOffset = plot.getPlotOffset(),
+ axisx = series.xaxis,
+ axisy = series.yaxis;
+
+ function plotDashes(xoffset, yoffset) {
+
+ var points = datapoints.points,
+ ps = datapoints.pointsize,
+ prevx = null,
+ prevy = null,
+ dashRemainder = 0,
+ dashOn = true,
+ dashOnLength,
+ dashOffLength;
+
+ if (series.dashes.dashLength[0]) {
+ dashOnLength = series.dashes.dashLength[0];
+ if (series.dashes.dashLength[1]) {
+ dashOffLength = series.dashes.dashLength[1];
+ } else {
+ dashOffLength = dashOnLength;
+ }
+ } else {
+ dashOffLength = dashOnLength = series.dashes.dashLength;
+ }
+
+ ctx.beginPath();
+
+ for (var i = ps; i < points.length; i += ps) {
+
+ var x1 = points[i - ps],
+ y1 = points[i - ps + 1],
+ x2 = points[i],
+ y2 = points[i + 1];
+
+ if (x1 == null || x2 == null) continue;
+
+ // clip with ymin
+ if (y1 <= y2 && y1 < axisy.min) {
+ if (y2 < axisy.min) continue; // line segment is outside
+ // compute new intersection point
+ x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+ y1 = axisy.min;
+ } else if (y2 <= y1 && y2 < axisy.min) {
+ if (y1 < axisy.min) continue;
+ x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+ y2 = axisy.min;
+ }
+
+ // clip with ymax
+ if (y1 >= y2 && y1 > axisy.max) {
+ if (y2 > axisy.max) continue;
+ x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+ y1 = axisy.max;
+ } else if (y2 >= y1 && y2 > axisy.max) {
+ if (y1 > axisy.max) continue;
+ x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+ y2 = axisy.max;
+ }
+
+ // clip with xmin
+ if (x1 <= x2 && x1 < axisx.min) {
+ if (x2 < axisx.min) continue;
+ y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+ x1 = axisx.min;
+ } else if (x2 <= x1 && x2 < axisx.min) {
+ if (x1 < axisx.min) continue;
+ y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+ x2 = axisx.min;
+ }
+
+ // clip with xmax
+ if (x1 >= x2 && x1 > axisx.max) {
+ if (x2 > axisx.max) continue;
+ y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+ x1 = axisx.max;
+ } else if (x2 >= x1 && x2 > axisx.max) {
+ if (x1 > axisx.max) continue;
+ y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+ x2 = axisx.max;
+ }
+
+ if (x1 != prevx || y1 != prevy) {
+ ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
+ }
+
+ var ax1 = axisx.p2c(x1) + xoffset,
+ ay1 = axisy.p2c(y1) + yoffset,
+ ax2 = axisx.p2c(x2) + xoffset,
+ ay2 = axisy.p2c(y2) + yoffset,
+ dashOffset;
+
+ function lineSegmentOffset(segmentLength) {
+
+ var c = Math.sqrt(Math.pow(ax2 - ax1, 2) + Math.pow(ay2 - ay1, 2));
+
+ if (c <= segmentLength) {
+ return {
+ deltaX: ax2 - ax1,
+ deltaY: ay2 - ay1,
+ distance: c,
+ remainder: segmentLength - c
+ }
+ } else {
+ var xsign = ax2 > ax1 ? 1 : -1,
+ ysign = ay2 > ay1 ? 1 : -1;
+ return {
+ deltaX: xsign * Math.sqrt(Math.pow(segmentLength, 2) / (1 + Math.pow((ay2 - ay1)/(ax2 - ax1), 2))),
+ deltaY: ysign * Math.sqrt(Math.pow(segmentLength, 2) - Math.pow(segmentLength, 2) / (1 + Math.pow((ay2 - ay1)/(ax2 - ax1), 2))),
+ distance: segmentLength,
+ remainder: 0
+ };
+ }
+ }
+ //-end lineSegmentOffset
+
+ do {
+
+ dashOffset = lineSegmentOffset(
+ dashRemainder > 0 ? dashRemainder :
+ dashOn ? dashOnLength : dashOffLength);
+
+ if (dashOffset.deltaX != 0 || dashOffset.deltaY != 0) {
+ if (dashOn) {
+ ctx.lineTo(ax1 + dashOffset.deltaX, ay1 + dashOffset.deltaY);
+ } else {
+ ctx.moveTo(ax1 + dashOffset.deltaX, ay1 + dashOffset.deltaY);
+ }
+ }
+
+ dashOn = !dashOn;
+ dashRemainder = dashOffset.remainder;
+ ax1 += dashOffset.deltaX;
+ ay1 += dashOffset.deltaY;
+
+ } while (dashOffset.distance > 0);
+
+ prevx = x2;
+ prevy = y2;
+ }
+
+ ctx.stroke();
+ }
+ //-end plotDashes
+
+ ctx.save();
+ ctx.translate(plotOffset.left, plotOffset.top);
+ ctx.lineJoin = 'round';
+
+ var lw = series.dashes.lineWidth,
+ sw = series.shadowSize;
+
+ // FIXME: consider another form of shadow when filling is turned on
+ if (lw > 0 && sw > 0) {
+ // draw shadow as a thick and thin line with transparency
+ ctx.lineWidth = sw;
+ ctx.strokeStyle = "rgba(0,0,0,0.1)";
+ // position shadow at angle from the mid of line
+ var angle = Math.PI/18;
+ plotDashes(Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2));
+ ctx.lineWidth = sw/2;
+ plotDashes(Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4));
+ }
+
+ ctx.lineWidth = lw;
+ ctx.strokeStyle = series.color;
+
+ if (lw > 0) {
+ plotDashes(0, 0);
+ }
+
+ ctx.restore();
+
+ });
+ //-end draw hook
+
+ });
+ //-end processDatapoints hook
+
+ }
+ //-end init
+
+ $.plot.plugins.push({
+ init: init,
+ options: {
+ series: {
+ dashes: {
+ show: false,
+ lineWidth: 2,
+ dashLength: 10
+ }
+ }
+ },
+ name: 'dashes',
+ version: '0.1'
+ });
+
+})(jQuery)
+
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.js b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.js
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.min.js b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.min.js
new file mode 100644
index 0000000..31f465b
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.min.js
@@ -0,0 +1 @@
+(function(){jQuery.color={};jQuery.color.make=function(G,H,J,I){var A={};A.r=G||0;A.g=H||0;A.b=J||0;A.a=I!=null?I:1;A.add=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]+=D}return A.normalize()};A.scale=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]*=D}return A.normalize()};A.toString=function(){if(A.a>=1){return"rgb("+[A.r,A.g,A.b].join(",")+")"}else{return"rgba("+[A.r,A.g,A.b,A.a].join(",")+")"}};A.normalize=function(){function C(E,D,F){return D<E?E:(D>F?F:D)}A.r=C(0,parseInt(A.r),255);A.g=C(0,parseInt(A.g),255);A.b=C(0,parseInt(A.b),255);A.a=C(0,A.a,1);return A};A.clone=function(){return jQuery.color.make(A.r,A.b,A.g,A.a)};return A.normalize()};jQuery.color.extract=function(E,F){var A;do{A=E.css(F).toLowerCase();if(A!=""&&A!="transparent"){break}E=E.parent()}while(!jQuery.nodeName(E.get(0),"body"));if(A=="rgba(0, 0, 0, 0)"){A="transparent"}return jQuery.color.parse(A)};jQuery.color.parse=function(A){var F,H=jQuery.color.make;if(F=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10))}if(F=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10),parseFloat(F[4]))}if(F=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55)}if(F=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55,parseFloat(F[4]))}if(F=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(A)){return H(parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16))}if(F=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(A)){return H(parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16))}var G=jQuery.trim(A).toLowerCase();if(G=="transparent"){return H(255,255,255,0)}else{F=B[G];return H(F[0],F[1],F[2])}};var B={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();(function(C){function B(l,W,X,E){var O=[],g={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{mode:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,tickDecimals:null,tickSize:null,minTickSize:null,monthNames:null,timeformat:null,twelveHourClock:false},yaxis:{autoscaleMargin:0.02},x2axis:{autoscaleMargin:null},y2axis:{autoscaleMargin:0.02},series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false},shadowSize:3},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,tickColor:"rgba(0,0,0,0.15)",labelMargin:5,borderWidth:2,borderColor:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},hooks:{}},P=null,AC=null,AD=null,Y=null,AJ=null,s={xaxis:{},yaxis:{},x2axis:{},y2axis:{}},e={left:0,right:0,top:0,bottom:0},y=0,Q=0,I=0,t=0,L={processOptions:[],processRawData:[],processDatapoints:[],draw:[],bindEvents:[],drawOverlay:[]},G=this;G.setData=f;G.setupGrid=k;G.draw=AH;G.getPlaceholder=function(){return l};G.getCanvas=function(){return P};G.getPlotOffset=function(){return e};G.width=function(){return I};G.height=function(){return t};G.offset=function(){var AK=AD.offset();AK.left+=e.left;AK.top+=e.top;return AK};G.getData=function(){return O};G.getAxes=function(){return s};G.getOptions=function(){return g};G.highlight=AE;G.unhighlight=x;G.triggerRedrawOverlay=q;G.pointOffset=function(AK){return{left:parseInt(T(AK,"xaxis").p2c(+AK.x)+e.left),top:parseInt(T(AK,"yaxis").p2c(+AK.y)+e.top)}};G.hooks=L;b(G);r(X);c();f(W);k();AH();AG();function Z(AM,AK){AK=[G].concat(AK);for(var AL=0;AL<AM.length;++AL){AM[AL].apply(this,AK)}}function b(){for(var AK=0;AK<E.length;++AK){var AL=E[AK];AL.init(G);if(AL.options){C.extend(true,g,AL.options)}}}function r(AK){C.extend(true,g,AK);if(g.grid.borderColor==null){g.grid.borderColor=g.grid.color}if(g.xaxis.noTicks&&g.xaxis.ticks==null){g.xaxis.ticks=g.xaxis.noTicks}if(g.yaxis.noTicks&&g.yaxis.ticks==null){g.yaxis.ticks=g.yaxis.noTicks}if(g.grid.coloredAreas){g.grid.markings=g.grid.coloredAreas}if(g.grid.coloredAreasColor){g.grid.markingsColor=g.grid.coloredAreasColor}if(g.lines){C.extend(true,g.series.lines,g.lines)}if(g.points){C.extend(true,g.series.points,g.points)}if(g.bars){C.extend(true,g.series.bars,g.bars)}if(g.shadowSize){g.series.shadowSize=g.shadowSize}for(var AL in L){if(g.hooks[AL]&&g.hooks[AL].length){L[AL]=L[AL].concat(g.hooks[AL])}}Z(L.processOptions,[g])}function f(AK){O=M(AK);U();m()}function M(AN){var AL=[];for(var AK=0;AK<AN.length;++AK){var AM=C.extend(true,{},g.series);if(AN[AK].data){AM.data=AN[AK].data;delete AN[AK].data;C.extend(true,AM,AN[AK]);AN[AK].data=AM.data}else{AM.data=AN[AK]}AL.push(AM)}return AL}function T(AM,AK){var AL=AM[AK];if(!AL||AL==1){return s[AK]}if(typeof AL=="number"){return s[AK.charAt(0)+AL+AK.slice(1)]}return AL}function U(){var AP;var AV=O.length,AK=[],AN=[];for(AP=0;AP<O.length;++AP){var AS=O[AP].color;if(AS!=null){--AV;if(typeof AS=="number"){AN.push(AS)}else{AK.push(C.color.parse(O[AP].color))}}}for(AP=0;AP<AN.length;++AP){AV=Math.max(AV,AN[AP]+1)}var AL=[],AO=0;AP=0;while(AL.length<AV){var AR;if(g.colors.length==AP){AR=C.color.make(100,100,100)}else{AR=C.color.parse(g.colors[AP])}var AM=AO%2==1?-1:1;AR.scale("rgb",1+AM*Math.ceil(AO/2)*0.2);AL.push(AR);++AP;if(AP>=g.colors.length){AP=0;++AO}}var AQ=0,AW;for(AP=0;AP<O.length;++AP){AW=O[AP];if(AW.color==null){AW.color=AL[AQ].toString();++AQ}else{if(typeof AW.color=="number"){AW.color=AL[AW.color].toString()}}if(AW.lines.show==null){var AU,AT=true;for(AU in AW){if(AW[AU].show){AT=false;break}}if(AT){AW.lines.show=true}}AW.xaxis=T(AW,"xaxis");AW.yaxis=T(AW,"yaxis")}}function m(){var AW=Number.POSITIVE_INFINITY,AQ=Number.NEGATIVE_INFINITY,Ac,Aa,AZ,AV,AL,AR,Ab,AX,AP,AO,AK,Ai,Af,AT;for(AK in s){s[AK].datamin=AW;s[AK].datamax=AQ;s[AK].used=false}function AN(Al,Ak,Aj){if(Ak<Al.datamin){Al.datamin=Ak}if(Aj>Al.datamax){Al.datamax=Aj}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];AR.datapoints={points:[]};Z(L.processRawData,[AR,AR.data,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];var Ah=AR.data,Ae=AR.datapoints.format;if(!Ae){Ae=[];Ae.push({x:true,number:true,required:true});Ae.push({y:true,number:true,required:true});if(AR.bars.show){Ae.push({y:true,number:true,required:false,defaultValue:0})}AR.datapoints.format=Ae}if(AR.datapoints.pointsize!=null){continue}if(AR.datapoints.pointsize==null){AR.datapoints.pointsize=Ae.length}AX=AR.datapoints.pointsize;Ab=AR.datapoints.points;insertSteps=AR.lines.show&&AR.lines.steps;AR.xaxis.used=AR.yaxis.used=true;for(Aa=AZ=0;Aa<Ah.length;++Aa,AZ+=AX){AT=Ah[Aa];var AM=AT==null;if(!AM){for(AV=0;AV<AX;++AV){Ai=AT[AV];Af=Ae[AV];if(Af){if(Af.number&&Ai!=null){Ai=+Ai;if(isNaN(Ai)){Ai=null}}if(Ai==null){if(Af.required){AM=true}if(Af.defaultValue!=null){Ai=Af.defaultValue}}}Ab[AZ+AV]=Ai}}if(AM){for(AV=0;AV<AX;++AV){Ai=Ab[AZ+AV];if(Ai!=null){Af=Ae[AV];if(Af.x){AN(AR.xaxis,Ai,Ai)}if(Af.y){AN(AR.yaxis,Ai,Ai)}}Ab[AZ+AV]=null}}else{if(insertSteps&&AZ>0&&Ab[AZ-AX]!=null&&Ab[AZ-AX]!=Ab[AZ]&&Ab[AZ-AX+1]!=Ab[AZ+1]){for(AV=0;AV<AX;++AV){Ab[AZ+AX+AV]=Ab[AZ+AV]}Ab[AZ+1]=Ab[AZ-AX+1];AZ+=AX}}}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Z(L.processDatapoints,[AR,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Ab=AR.datapoints.points,AX=AR.datapoints.pointsize;var AS=AW,AY=AW,AU=AQ,Ad=AQ;for(Aa=0;Aa<Ab.length;Aa+=AX){if(Ab[Aa]==null){continue}for(AV=0;AV<AX;++AV){Ai=Ab[Aa+AV];Af=Ae[AV];if(!Af){continue}if(Af.x){if(Ai<AS){AS=Ai}if(Ai>AU){AU=Ai}}if(Af.y){if(Ai<AY){AY=Ai}if(Ai>Ad){Ad=Ai}}}}if(AR.bars.show){var Ag=AR.bars.align=="left"?0:-AR.bars.barWidth/2;if(AR.bars.horizontal){AY+=Ag;Ad+=Ag+AR.bars.barWidth}else{AS+=Ag;AU+=Ag+AR.bars.barWidth}}AN(AR.xaxis,AS,AU);AN(AR.yaxis,AY,Ad)}for(AK in s){if(s[AK].datamin==AW){s[AK].datamin=null}if(s[AK].datamax==AQ){s[AK].datamax=null}}}function c(){function AK(AM,AL){var AN=document.createElement("canvas");AN.width=AM;AN.height=AL;if(C.browser.msie){AN=window.G_vmlCanvasManager.initElement(AN)}return AN}y=l.width();Q=l.height();l.html("");if(l.css("position")=="static"){l.css("position","relative")}if(y<=0||Q<=0){throw"Invalid dimensions for plot, width = "+y+", height = "+Q}if(C.browser.msie){window.G_vmlCanvasManager.init_(document)}P=C(AK(y,Q)).appendTo(l).get(0);Y=P.getContext("2d");AC=C(AK(y,Q)).css({position:"absolute",left:0,top:0}).appendTo(l).get(0);AJ=AC.getContext("2d");AJ.stroke()}function AG(){AD=C([AC,P]);if(g.grid.hoverable){AD.mousemove(D)}if(g.grid.clickable){AD.click(d)}Z(L.bindEvents,[AD])}function k(){function AL(AT,AU){function AP(AV){return AV}var AS,AO,AQ=AU.transform||AP,AR=AU.inverseTransform;if(AT==s.xaxis||AT==s.x2axis){AS=AT.scale=I/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.min);if(AQ==AP){AT.p2c=function(AV){return(AV-AO)*AS}}else{AT.p2c=function(AV){return(AQ(AV)-AO)*AS}}if(!AR){AT.c2p=function(AV){return AO+AV/AS}}else{AT.c2p=function(AV){return AR(AO+AV/AS)}}}else{AS=AT.scale=t/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.max);if(AQ==AP){AT.p2c=function(AV){return(AO-AV)*AS}}else{AT.p2c=function(AV){return(AO-AQ(AV))*AS}}if(!AR){AT.c2p=function(AV){return AO-AV/AS}}else{AT.c2p=function(AV){return AR(AO-AV/AS)}}}}function AN(AR,AT){var AQ,AS=[],AP;AR.labelWidth=AT.labelWidth;AR.labelHeight=AT.labelHeight;if(AR==s.xaxis||AR==s.x2axis){if(AR.labelWidth==null){AR.labelWidth=y/(AR.ticks.length>0?AR.ticks.length:1)}if(AR.labelHeight==null){AS=[];for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel" style="float:left;width:'+AR.labelWidth+'px">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">'+AS.join("")+'<div style="clear:left"></div></div>').appendTo(l);AR.labelHeight=AO.height();AO.remove()}}}else{if(AR.labelWidth==null||AR.labelHeight==null){for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;font-size:smaller">'+AS.join("")+"</div>").appendTo(l);if(AR.labelWidth==null){AR.labelWidth=AO.width()}if(AR.labelHeight==null){AR.labelHeight=AO.find("div").height()}AO.remove()}}}if(AR.labelWidth==null){AR.labelWidth=0}if(AR.labelHeight==null){AR.labelHeight=0}}function AM(){var AP=g.grid.borderWidth;for(i=0;i<O.length;++i){AP=Math.max(AP,2*(O[i].points.radius+O[i].points.lineWidth/2))}e.left=e.right=e.top=e.bottom=AP;var AO=g.grid.labelMargin+g.grid.borderWidth;if(s.xaxis.labelHeight>0){e.bottom=Math.max(AP,s.xaxis.labelHeight+AO)}if(s.yaxis.labelWidth>0){e.left=Math.max(AP,s.yaxis.labelWidth+AO)}if(s.x2axis.labelHeight>0){e.top=Math.max(AP,s.x2axis.labelHeight+AO)}if(s.y2axis.labelWidth>0){e.right=Math.max(AP,s.y2axis.labelWidth+AO)}I=y-e.left-e.right;t=Q-e.bottom-e.top}var AK;for(AK in s){K(s[AK],g[AK])}if(g.grid.show){for(AK in s){F(s[AK],g[AK]);p(s[AK],g[AK]);AN(s[AK],g[AK])}AM()}else{e.left=e.right=e.top=e.bottom=0;I=y;t=Q}for(AK in s){AL(s[AK],g[AK])}if(g.grid.show){h()}AI()}function K(AN,AQ){var AM=+(AQ.min!=null?AQ.min:AN.datamin),AK=+(AQ.max!=null?AQ.max:AN.datamax),AP=AK-AM;if(AP==0){var AL=AK==0?1:0.01;if(AQ.min==null){AM-=AL}if(AQ.max==null||AQ.min!=null){AK+=AL}}else{var AO=AQ.autoscaleMargin;if(AO!=null){if(AQ.min==null){AM-=AP*AO;if(AM<0&&AN.datamin!=null&&AN.datamin>=0){AM=0}}if(AQ.max==null){AK+=AP*AO;if(AK>0&&AN.datamax!=null&&AN.datamax<=0){AK=0}}}}AN.min=AM;AN.max=AK}function F(AP,AS){var AO;if(typeof AS.ticks=="number"&&AS.ticks>0){AO=AS.ticks}else{if(AP==s.xaxis||AP==s.x2axis){AO=0.3*Math.sqrt(y)}else{AO=0.3*Math.sqrt(Q)}}var AX=(AP.max-AP.min)/AO,AZ,AT,AV,AW,AR,AM,AL;if(AS.mode=="time"){var AU={second:1000,minute:60*1000,hour:60*60*1000,day:24*60*60*1000,month:30*24*60*60*1000,year:365.2425*24*60*60*1000};var AY=[[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]];var AN=0;if(AS.minTickSize!=null){if(typeof AS.tickSize=="number"){AN=AS.tickSize}else{AN=AS.minTickSize[0]*AU[AS.minTickSize[1]]}}for(AR=0;AR<AY.length-1;++AR){if(AX<(AY[AR][0]*AU[AY[AR][1]]+AY[AR+1][0]*AU[AY[AR+1][1]])/2&&AY[AR][0]*AU[AY[AR][1]]>=AN){break}}AZ=AY[AR][0];AV=AY[AR][1];if(AV=="year"){AM=Math.pow(10,Math.floor(Math.log(AX/AU.year)/Math.LN10));AL=(AX/AU.year)/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM}if(AS.tickSize){AZ=AS.tickSize[0];AV=AS.tickSize[1]}AT=function(Ac){var Ah=[],Af=Ac.tickSize[0],Ai=Ac.tickSize[1],Ag=new Date(Ac.min);var Ab=Af*AU[Ai];if(Ai=="second"){Ag.setUTCSeconds(A(Ag.getUTCSeconds(),Af))}if(Ai=="minute"){Ag.setUTCMinutes(A(Ag.getUTCMinutes(),Af))}if(Ai=="hour"){Ag.setUTCHours(A(Ag.getUTCHours(),Af))}if(Ai=="month"){Ag.setUTCMonth(A(Ag.getUTCMonth(),Af))}if(Ai=="year"){Ag.setUTCFullYear(A(Ag.getUTCFullYear(),Af))}Ag.setUTCMilliseconds(0);if(Ab>=AU.minute){Ag.setUTCSeconds(0)}if(Ab>=AU.hour){Ag.setUTCMinutes(0)}if(Ab>=AU.day){Ag.setUTCHours(0)}if(Ab>=AU.day*4){Ag.setUTCDate(1)}if(Ab>=AU.year){Ag.setUTCMonth(0)}var Ak=0,Aj=Number.NaN,Ad;do{Ad=Aj;Aj=Ag.getTime();Ah.push({v:Aj,label:Ac.tickFormatter(Aj,Ac)});if(Ai=="month"){if(Af<1){Ag.setUTCDate(1);var Aa=Ag.getTime();Ag.setUTCMonth(Ag.getUTCMonth()+1);var Ae=Ag.getTime();Ag.setTime(Aj+Ak*AU.hour+(Ae-Aa)*Af);Ak=Ag.getUTCHours();Ag.setUTCHours(0)}else{Ag.setUTCMonth(Ag.getUTCMonth()+Af)}}else{if(Ai=="year"){Ag.setUTCFullYear(Ag.getUTCFullYear()+Af)}else{Ag.setTime(Aj+Ab)}}}while(Aj<Ac.max&&Aj!=Ad);return Ah};AW=function(Aa,Ad){var Af=new Date(Aa);if(AS.timeformat!=null){return C.plot.formatDate(Af,AS.timeformat,AS.monthNames)}var Ab=Ad.tickSize[0]*AU[Ad.tickSize[1]];var Ac=Ad.max-Ad.min;var Ae=(AS.twelveHourClock)?" %p":"";if(Ab<AU.minute){fmt="%h:%M:%S"+Ae}else{if(Ab<AU.day){if(Ac<2*AU.day){fmt="%h:%M"+Ae}else{fmt="%b %d %h:%M"+Ae}}else{if(Ab<AU.month){fmt="%b %d"}else{if(Ab<AU.year){if(Ac<AU.year){fmt="%b"}else{fmt="%b %y"}}else{fmt="%y"}}}}return C.plot.formatDate(Af,fmt,AS.monthNames)}}else{var AK=AS.tickDecimals;var AQ=-Math.floor(Math.log(AX)/Math.LN10);if(AK!=null&&AQ>AK){AQ=AK}AM=Math.pow(10,-AQ);AL=AX/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2;if(AL>2.25&&(AK==null||AQ+1<=AK)){AZ=2.5;++AQ}}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM;if(AS.minTickSize!=null&&AZ<AS.minTickSize){AZ=AS.minTickSize}if(AS.tickSize!=null){AZ=AS.tickSize}AP.tickDecimals=Math.max(0,(AK!=null)?AK:AQ);AT=function(Ac){var Ae=[];var Af=A(Ac.min,Ac.tickSize),Ab=0,Aa=Number.NaN,Ad;do{Ad=Aa;Aa=Af+Ab*Ac.tickSize;Ae.push({v:Aa,label:Ac.tickFormatter(Aa,Ac)});++Ab}while(Aa<Ac.max&&Aa!=Ad);return Ae};AW=function(Aa,Ab){return Aa.toFixed(Ab.tickDecimals)}}AP.tickSize=AV?[AZ,AV]:AZ;AP.tickGenerator=AT;if(C.isFunction(AS.tickFormatter)){AP.tickFormatter=function(Aa,Ab){return""+AS.tickFormatter(Aa,Ab)}}else{AP.tickFormatter=AW}}function p(AO,AQ){AO.ticks=[];if(!AO.used){return }if(AQ.ticks==null){AO.ticks=AO.tickGenerator(AO)}else{if(typeof AQ.ticks=="number"){if(AQ.ticks>0){AO.ticks=AO.tickGenerator(AO)}}else{if(AQ.ticks){var AP=AQ.ticks;if(C.isFunction(AP)){AP=AP({min:AO.min,max:AO.max})}var AN,AK;for(AN=0;AN<AP.length;++AN){var AL=null;var AM=AP[AN];if(typeof AM=="object"){AK=AM[0];if(AM.length>1){AL=AM[1]}}else{AK=AM}if(AL==null){AL=AO.tickFormatter(AK,AO)}AO.ticks[AN]={v:AK,label:AL}}}}}if(AQ.autoscaleMargin!=null&&AO.ticks.length>0){if(AQ.min==null){AO.min=Math.min(AO.min,AO.ticks[0].v)}if(AQ.max==null&&AO.ticks.length>1){AO.max=Math.max(AO.max,AO.ticks[AO.ticks.length-1].v)}}}function AH(){Y.clearRect(0,0,y,Q);var AL=g.grid;if(AL.show&&!AL.aboveData){S()}for(var AK=0;AK<O.length;++AK){AA(O[AK])}Z(L.draw,[Y]);if(AL.show&&AL.aboveData){S()}}function N(AL,AR){var AO=AR+"axis",AK=AR+"2axis",AN,AQ,AP,AM;if(AL[AO]){AN=s[AO];AQ=AL[AO].from;AP=AL[AO].to}else{if(AL[AK]){AN=s[AK];AQ=AL[AK].from;AP=AL[AK].to}else{AN=s[AO];AQ=AL[AR+"1"];AP=AL[AR+"2"]}}if(AQ!=null&&AP!=null&&AQ>AP){return{from:AP,to:AQ,axis:AN}}return{from:AQ,to:AP,axis:AN}}function S(){var AO;Y.save();Y.translate(e.left,e.top);if(g.grid.backgroundColor){Y.fillStyle=R(g.grid.backgroundColor,t,0,"rgba(255, 255, 255, 0)");Y.fillRect(0,0,I,t)}var AL=g.grid.markings;if(AL){if(C.isFunction(AL)){AL=AL({xmin:s.xaxis.min,xmax:s.xaxis.max,ymin:s.yaxis.min,ymax:s.yaxis.max,xaxis:s.xaxis,yaxis:s.yaxis,x2axis:s.x2axis,y2axis:s.y2axis})}for(AO=0;AO<AL.length;++AO){var AK=AL[AO],AQ=N(AK,"x"),AN=N(AK,"y");if(AQ.from==null){AQ.from=AQ.axis.min}if(AQ.to==null){AQ.to=AQ.axis.max}if(AN.from==null){AN.from=AN.axis.min}if(AN.to==null){AN.to=AN.axis.max}if(AQ.to<AQ.axis.min||AQ.from>AQ.axis.max||AN.to<AN.axis.min||AN.from>AN.axis.max){continue}AQ.from=Math.max(AQ.from,AQ.axis.min);AQ.to=Math.min(AQ.to,AQ.axis.max);AN.from=Math.max(AN.from,AN.axis.min);AN.to=Math.min(AN.to,AN.axis.max);if(AQ.from==AQ.to&&AN.from==AN.to){continue}AQ.from=AQ.axis.p2c(AQ.from);AQ.to=AQ.axis.p2c(AQ.to);AN.from=AN.axis.p2c(AN.from);AN.to=AN.axis.p2c(AN.to);if(AQ.from==AQ.to||AN.from==AN.to){Y.beginPath();Y.strokeStyle=AK.color||g.grid.markingsColor;Y.lineWidth=AK.lineWidth||g.grid.markingsLineWidth;Y.moveTo(AQ.from,AN.from);Y.lineTo(AQ.to,AN.to);Y.stroke()}else{Y.fillStyle=AK.color||g.grid.markingsColor;Y.fillRect(AQ.from,AN.to,AQ.to-AQ.from,AN.from-AN.to)}}}Y.lineWidth=1;Y.strokeStyle=g.grid.tickColor;Y.beginPath();var AM,AP=s.xaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=s.xaxis.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,0);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,t)}AP=s.yaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(0,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}AP=s.x2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,-5);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,5)}AP=s.y2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(I-5,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I+5,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}Y.stroke();if(g.grid.borderWidth){var AR=g.grid.borderWidth;Y.lineWidth=AR;Y.strokeStyle=g.grid.borderColor;Y.strokeRect(-AR/2,-AR/2,I+AR,t+AR)}Y.restore()}function h(){l.find(".tickLabels").remove();var AK=['<div class="tickLabels" style="font-size:smaller;color:'+g.grid.color+'">'];function AM(AP,AQ){for(var AO=0;AO<AP.ticks.length;++AO){var AN=AP.ticks[AO];if(!AN.label||AN.v<AP.min||AN.v>AP.max){continue}AK.push(AQ(AN,AP))}}var AL=g.grid.labelMargin+g.grid.borderWidth;AM(s.xaxis,function(AN,AO){return'<div style="position:absolute;top:'+(e.top+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.yaxis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;right:"+(e.right+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:right" class="tickLabel">'+AN.label+"</div>"});AM(s.x2axis,function(AN,AO){return'<div style="position:absolute;bottom:'+(e.bottom+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.y2axis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;left:"+(e.left+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:left" class="tickLabel">'+AN.label+"</div>"});AK.push("</div>");l.append(AK.join(""))}function AA(AK){if(AK.lines.show){a(AK)}if(AK.bars.show){n(AK)}if(AK.points.show){o(AK)}}function a(AN){function AM(AY,AZ,AR,Ad,Ac){var Ae=AY.points,AS=AY.pointsize,AW=null,AV=null;Y.beginPath();for(var AX=AS;AX<Ae.length;AX+=AS){var AU=Ae[AX-AS],Ab=Ae[AX-AS+1],AT=Ae[AX],Aa=Ae[AX+1];if(AU==null||AT==null){continue}if(Ab<=Aa&&Ab<Ac.min){if(Aa<Ac.min){continue}AU=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(Aa<=Ab&&Aa<Ac.min){if(Ab<Ac.min){continue}AT=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.min}}if(Ab>=Aa&&Ab>Ac.max){if(Aa>Ac.max){continue}AU=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(Aa>=Ab&&Aa>Ac.max){if(Ab>Ac.max){continue}AT=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.max}}if(AU<=AT&&AU<Ad.min){if(AT<Ad.min){continue}Ab=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.min}else{if(AT<=AU&&AT<Ad.min){if(AU<Ad.min){continue}Aa=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.min}}if(AU>=AT&&AU>Ad.max){if(AT>Ad.max){continue}Ab=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.max}else{if(AT>=AU&&AT>Ad.max){if(AU>Ad.max){continue}Aa=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.max}}if(AU!=AW||Ab!=AV){Y.moveTo(Ad.p2c(AU)+AZ,Ac.p2c(Ab)+AR)}AW=AT;AV=Aa;Y.lineTo(Ad.p2c(AT)+AZ,Ac.p2c(Aa)+AR)}Y.stroke()}function AO(AX,Ae,Ac){var Af=AX.points,AR=AX.pointsize,AS=Math.min(Math.max(0,Ac.min),Ac.max),Aa,AV=0,Ad=false;for(var AW=AR;AW<Af.length;AW+=AR){var AU=Af[AW-AR],Ab=Af[AW-AR+1],AT=Af[AW],AZ=Af[AW+1];if(Ad&&AU!=null&&AT==null){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill();Ad=false;continue}if(AU==null||AT==null){continue}if(AU<=AT&&AU<Ae.min){if(AT<Ae.min){continue}Ab=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.min}else{if(AT<=AU&&AT<Ae.min){if(AU<Ae.min){continue}AZ=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.min}}if(AU>=AT&&AU>Ae.max){if(AT>Ae.max){continue}Ab=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.max}else{if(AT>=AU&&AT>Ae.max){if(AU>Ae.max){continue}AZ=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.max}}if(!Ad){Y.beginPath();Y.moveTo(Ae.p2c(AU),Ac.p2c(AS));Ad=true}if(Ab>=Ac.max&&AZ>=Ac.max){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.max));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.max));AV=AT;continue}else{if(Ab<=Ac.min&&AZ<=Ac.min){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.min));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.min));AV=AT;continue}}var Ag=AU,AY=AT;if(Ab<=AZ&&Ab<Ac.min&&AZ>=Ac.min){AU=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(AZ<=Ab&&AZ<Ac.min&&Ab>=Ac.min){AT=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.min}}if(Ab>=AZ&&Ab>Ac.max&&AZ<=Ac.max){AU=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(AZ>=Ab&&AZ>Ac.max&&Ab<=Ac.max){AT=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.max}}if(AU!=Ag){if(Ab<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(Ag),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AU),Ac.p2c(Aa))}Y.lineTo(Ae.p2c(AU),Ac.p2c(Ab));Y.lineTo(Ae.p2c(AT),Ac.p2c(AZ));if(AT!=AY){if(AZ<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(AT),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AY),Ac.p2c(Aa))}AV=Math.max(AT,AY)}if(Ad){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill()}}Y.save();Y.translate(e.left,e.top);Y.lineJoin="round";var AP=AN.lines.lineWidth,AK=AN.shadowSize;if(AP>0&&AK>0){Y.lineWidth=AK;Y.strokeStyle="rgba(0,0,0,0.1)";var AQ=Math.PI/18;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/2),Math.cos(AQ)*(AP/2+AK/2),AN.xaxis,AN.yaxis);Y.lineWidth=AK/2;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/4),Math.cos(AQ)*(AP/2+AK/4),AN.xaxis,AN.yaxis)}Y.lineWidth=AP;Y.strokeStyle=AN.color;var AL=V(AN.lines,AN.color,0,t);if(AL){Y.fillStyle=AL;AO(AN.datapoints,AN.xaxis,AN.yaxis)}if(AP>0){AM(AN.datapoints,0,0,AN.xaxis,AN.yaxis)}Y.restore()}function o(AN){function AP(AU,AT,Ab,AR,AV,AZ,AY){var Aa=AU.points,AQ=AU.pointsize;for(var AS=0;AS<Aa.length;AS+=AQ){var AX=Aa[AS],AW=Aa[AS+1];if(AX==null||AX<AZ.min||AX>AZ.max||AW<AY.min||AW>AY.max){continue}Y.beginPath();Y.arc(AZ.p2c(AX),AY.p2c(AW)+AR,AT,0,AV,false);if(Ab){Y.fillStyle=Ab;Y.fill()}Y.stroke()}}Y.save();Y.translate(e.left,e.top);var AO=AN.lines.lineWidth,AL=AN.shadowSize,AK=AN.points.radius;if(AO>0&&AL>0){var AM=AL/2;Y.lineWidth=AM;Y.strokeStyle="rgba(0,0,0,0.1)";AP(AN.datapoints,AK,null,AM+AM/2,Math.PI,AN.xaxis,AN.yaxis);Y.strokeStyle="rgba(0,0,0,0.2)";AP(AN.datapoints,AK,null,AM/2,Math.PI,AN.xaxis,AN.yaxis)}Y.lineWidth=AO;Y.strokeStyle=AN.color;AP(AN.datapoints,AK,V(AN.points,AN.color),0,2*Math.PI,AN.xaxis,AN.yaxis);Y.restore()}function AB(AV,AU,Ad,AQ,AY,AN,AL,AT,AS,Ac,AZ){var AM,Ab,AR,AX,AO,AK,AW,AP,Aa;if(AZ){AP=AK=AW=true;AO=false;AM=Ad;Ab=AV;AX=AU+AQ;AR=AU+AY;if(Ab<AM){Aa=Ab;Ab=AM;AM=Aa;AO=true;AK=false}}else{AO=AK=AW=true;AP=false;AM=AV+AQ;Ab=AV+AY;AR=Ad;AX=AU;if(AX<AR){Aa=AX;AX=AR;AR=Aa;AP=true;AW=false}}if(Ab<AT.min||AM>AT.max||AX<AS.min||AR>AS.max){return }if(AM<AT.min){AM=AT.min;AO=false}if(Ab>AT.max){Ab=AT.max;AK=false}if(AR<AS.min){AR=AS.min;AP=false}if(AX>AS.max){AX=AS.max;AW=false}AM=AT.p2c(AM);AR=AS.p2c(AR);Ab=AT.p2c(Ab);AX=AS.p2c(AX);if(AL){Ac.beginPath();Ac.moveTo(AM,AR);Ac.lineTo(AM,AX);Ac.lineTo(Ab,AX);Ac.lineTo(Ab,AR);Ac.fillStyle=AL(AR,AX);Ac.fill()}if(AO||AK||AW||AP){Ac.beginPath();Ac.moveTo(AM,AR+AN);if(AO){Ac.lineTo(AM,AX+AN)}else{Ac.moveTo(AM,AX+AN)}if(AW){Ac.lineTo(Ab,AX+AN)}else{Ac.moveTo(Ab,AX+AN)}if(AK){Ac.lineTo(Ab,AR+AN)}else{Ac.moveTo(Ab,AR+AN)}if(AP){Ac.lineTo(AM,AR+AN)}else{Ac.moveTo(AM,AR+AN)}Ac.stroke()}}function n(AM){function AL(AS,AR,AU,AP,AT,AW,AV){var AX=AS.points,AO=AS.pointsize;for(var AQ=0;AQ<AX.length;AQ+=AO){if(AX[AQ]==null){continue}AB(AX[AQ],AX[AQ+1],AX[AQ+2],AR,AU,AP,AT,AW,AV,Y,AM.bars.horizontal)}}Y.save();Y.translate(e.left,e.top);Y.lineWidth=AM.bars.lineWidth;Y.strokeStyle=AM.color;var AK=AM.bars.align=="left"?0:-AM.bars.barWidth/2;var AN=AM.bars.fill?function(AO,AP){return V(AM.bars,AM.color,AO,AP)}:null;AL(AM.datapoints,AK,AK+AM.bars.barWidth,0,AN,AM.xaxis,AM.yaxis);Y.restore()}function V(AM,AK,AL,AO){var AN=AM.fill;if(!AN){return null}if(AM.fillColor){return R(AM.fillColor,AL,AO,AK)}var AP=C.color.parse(AK);AP.a=typeof AN=="number"?AN:0.4;AP.normalize();return AP.toString()}function AI(){l.find(".legend").remove();if(!g.legend.show){return }var AP=[],AN=false,AV=g.legend.labelFormatter,AU,AR;for(i=0;i<O.length;++i){AU=O[i];AR=AU.label;if(!AR){continue}if(i%g.legend.noColumns==0){if(AN){AP.push("</tr>")}AP.push("<tr>");AN=true}if(AV){AR=AV(AR,AU)}AP.push('<td class="legendColorBox"><div style="border:1px solid '+g.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+AU.color+';overflow:hidden"></div></div></td><td class="legendLabel">'+AR+"</td>")}if(AN){AP.push("</tr>")}if(AP.length==0){return }var AT='<table style="font-size:smaller;color:'+g.grid.color+'">'+AP.join("")+"</table>";if(g.legend.container!=null){C(g.legend.container).html(AT)}else{var AQ="",AL=g.legend.position,AM=g.legend.margin;if(AM[0]==null){AM=[AM,AM]}if(AL.charAt(0)=="n"){AQ+="top:"+(AM[1]+e.top)+"px;"}else{if(AL.charAt(0)=="s"){AQ+="bottom:"+(AM[1]+e.bottom)+"px;"}}if(AL.charAt(1)=="e"){AQ+="right:"+(AM[0]+e.right)+"px;"}else{if(AL.charAt(1)=="w"){AQ+="left:"+(AM[0]+e.left)+"px;"}}var AS=C('<div class="legend">'+AT.replace('style="','style="position:absolute;'+AQ+";")+"</div>").appendTo(l);if(g.legend.backgroundOpacity!=0){var AO=g.legend.backgroundColor;if(AO==null){AO=g.grid.backgroundColor;if(AO&&typeof AO=="string"){AO=C.color.parse(AO)}else{AO=C.color.extract(AS,"background-color")}AO.a=1;AO=AO.toString()}var AK=AS.children();C('<div style="position:absolute;width:'+AK.width()+"px;height:"+AK.height()+"px;"+AQ+"background-color:"+AO+';"> </div>').prependTo(AS).css("opacity",g.legend.backgroundOpacity)}}}var w=[],J=null;function AF(AR,AP,AM){var AX=g.grid.mouseActiveRadius,Aj=AX*AX+1,Ah=null,Aa=false,Af,Ad;for(Af=0;Af<O.length;++Af){if(!AM(O[Af])){continue}var AY=O[Af],AQ=AY.xaxis,AO=AY.yaxis,Ae=AY.datapoints.points,Ac=AY.datapoints.pointsize,AZ=AQ.c2p(AR),AW=AO.c2p(AP),AL=AX/AQ.scale,AK=AX/AO.scale;if(AY.lines.show||AY.points.show){for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1];if(AT==null){continue}if(AT-AZ>AL||AT-AZ<-AL||AS-AW>AK||AS-AW<-AK){continue}var AV=Math.abs(AQ.p2c(AT)-AR),AU=Math.abs(AO.p2c(AS)-AP),Ab=AV*AV+AU*AU;if(Ab<=Aj){Aj=Ab;Ah=[Af,Ad/Ac]}}}if(AY.bars.show&&!Ah){var AN=AY.bars.align=="left"?0:-AY.bars.barWidth/2,Ag=AN+AY.bars.barWidth;for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1],Ai=Ae[Ad+2];if(AT==null){continue}if(O[Af].bars.horizontal?(AZ<=Math.max(Ai,AT)&&AZ>=Math.min(Ai,AT)&&AW>=AS+AN&&AW<=AS+Ag):(AZ>=AT+AN&&AZ<=AT+Ag&&AW>=Math.min(Ai,AS)&&AW<=Math.max(Ai,AS))){Ah=[Af,Ad/Ac]}}}}if(Ah){Af=Ah[0];Ad=Ah[1];Ac=O[Af].datapoints.pointsize;return{datapoint:O[Af].datapoints.points.slice(Ad*Ac,(Ad+1)*Ac),dataIndex:Ad,series:O[Af],seriesIndex:Af}}return null}function D(AK){if(g.grid.hoverable){H("plothover",AK,function(AL){return AL.hoverable!=false})}}function d(AK){H("plotclick",AK,function(AL){return AL.clickable!=false})}function H(AL,AK,AM){var AN=AD.offset(),AS={pageX:AK.pageX,pageY:AK.pageY},AQ=AK.pageX-AN.left-e.left,AO=AK.pageY-AN.top-e.top;if(s.xaxis.used){AS.x=s.xaxis.c2p(AQ)}if(s.yaxis.used){AS.y=s.yaxis.c2p(AO)}if(s.x2axis.used){AS.x2=s.x2axis.c2p(AQ)}if(s.y2axis.used){AS.y2=s.y2axis.c2p(AO)}var AT=AF(AQ,AO,AM);if(AT){AT.pageX=parseInt(AT.series.xaxis.p2c(AT.datapoint[0])+AN.left+e.left);AT.pageY=parseInt(AT.series.yaxis.p2c(AT.datapoint[1])+AN.top+e.top)}if(g.grid.autoHighlight){for(var AP=0;AP<w.length;++AP){var AR=w[AP];if(AR.auto==AL&&!(AT&&AR.series==AT.series&&AR.point==AT.datapoint)){x(AR.series,AR.point)}}if(AT){AE(AT.series,AT.datapoint,AL)}}l.trigger(AL,[AS,AT])}function q(){if(!J){J=setTimeout(v,30)}}function v(){J=null;AJ.save();AJ.clearRect(0,0,y,Q);AJ.translate(e.left,e.top);var AL,AK;for(AL=0;AL<w.length;++AL){AK=w[AL];if(AK.series.bars.show){z(AK.series,AK.point)}else{u(AK.series,AK.point)}}AJ.restore();Z(L.drawOverlay,[AJ])}function AE(AM,AK,AN){if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL==-1){w.push({series:AM,point:AK,auto:AN});q()}else{if(!AN){w[AL].auto=false}}}function x(AM,AK){if(AM==null&&AK==null){w=[];q()}if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL!=-1){w.splice(AL,1);q()}}function j(AM,AN){for(var AK=0;AK<w.length;++AK){var AL=w[AK];if(AL.series==AM&&AL.point[0]==AN[0]&&AL.point[1]==AN[1]){return AK}}return -1}function u(AN,AM){var AL=AM[0],AR=AM[1],AQ=AN.xaxis,AP=AN.yaxis;if(AL<AQ.min||AL>AQ.max||AR<AP.min||AR>AP.max){return }var AO=AN.points.radius+AN.points.lineWidth/2;AJ.lineWidth=AO;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AK=1.5*AO;AJ.beginPath();AJ.arc(AQ.p2c(AL),AP.p2c(AR),AK,0,2*Math.PI,false);AJ.stroke()}function z(AN,AK){AJ.lineWidth=AN.bars.lineWidth;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AM=C.color.parse(AN.color).scale("a",0.5).toString();var AL=AN.bars.align=="left"?0:-AN.bars.barWidth/2;AB(AK[0],AK[1],AK[2]||0,AL,AL+AN.bars.barWidth,0,function(){return AM},AN.xaxis,AN.yaxis,AJ,AN.bars.horizontal)}function R(AM,AL,AQ,AO){if(typeof AM=="string"){return AM}else{var AP=Y.createLinearGradient(0,AQ,0,AL);for(var AN=0,AK=AM.colors.length;AN<AK;++AN){var AR=AM.colors[AN];if(typeof AR!="string"){AR=C.color.parse(AO).scale("rgb",AR.brightness);AR.a*=AR.opacity;AR=AR.toString()}AP.addColorStop(AN/(AK-1),AR)}return AP}}}C.plot=function(G,E,D){var F=new B(C(G),E,D,C.plot.plugins);return F};C.plot.plugins=[];C.plot.formatDate=function(H,E,G){var L=function(N){N=""+N;return N.length==1?"0"+N:N};var D=[];var M=false;var K=H.getUTCHours();var I=K<12;if(G==null){G=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}if(E.search(/%p|%P/)!=-1){if(K>12){K=K-12}else{if(K==0){K=12}}}for(var F=0;F<E.length;++F){var J=E.charAt(F);if(M){switch(J){case"h":J=""+K;break;case"H":J=L(K);break;case"M":J=L(H.getUTCMinutes());break;case"S":J=L(H.getUTCSeconds());break;case"d":J=""+H.getUTCDate();break;case"m":J=""+(H.getUTCMonth()+1);break;case"y":J=""+H.getUTCFullYear();break;case"b":J=""+G[H.getUTCMonth()];break;case"p":J=(I)?("am"):("pm");break;case"P":J=(I)?("AM"):("PM");break}D.push(J);M=false}else{if(J=="%"){M=true}else{D.push(J)}}}return D.join("")};function A(E,D){return D*Math.floor(E/D)}})(jQuery); \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.navigate.js b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.navigate.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.navigate.js
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.valuelabels.js b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.valuelabels.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.valuelabels.js
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/options.html b/chrome/common/extensions/docs/examples/extensions/benchmark/options.html
index 4a09047..24adc77 100644
--- a/chrome/common/extensions/docs/examples/extensions/benchmark/options.html
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/options.html
@@ -4,7 +4,11 @@
<script src="jst/util.js" type="text/javascript"></script>
<script src="jst/jsevalcontext.js" type="text/javascript"></script>
<script src="jst/jstemplate.js" type="text/javascript"></script>
- <script src="jst/jstemplate_example.js" type="text/javascript"></script>
+ <script src="jquery/jquery-1.4.2.min.js" type="text/javascript"></script>
+ <script src="jquery/jquery.flot.min.js" type="text/javascript"></script>
+ <script src="jquery/jquery.flot.dashes.js" type="text/javascript"></script>
+ <script src="util/table2CSV.js" type="text/javascript"></script>
+ <script src="util/sorttable.js" type="text/javascript"></script>
<style>
body {
@@ -54,16 +58,16 @@ div#header p {
display: inline;
}
-table.list {
+table.sortable {
font-size: 84%;
table-layout: fixed;
}
-table.list:not([class*='filtered']) tr:nth-child(odd) td:not([class*='filtered']) {
+table.sortable:not([class*='filtered']) tr:nth-child(even) td:not([class*='filtered']) {
background: #eff3ff;
}
-table.list th {
+.nobg {
padding: 0 0.5em;
vertical-align: bottom;
font-weight: bold;
@@ -72,6 +76,20 @@ table.list th {
text-align: center;
}
+.bg{
+ padding: 0 0.5em;
+ vertical-align: bottom;
+ font-weight: bold;
+ color: #315d94;
+ color: black;
+ text-align: center;
+ cursor: pointer;
+}
+
+.bg:hover {
+ background: #eff3aa;
+}
+
.avg {
font-weight: bold;
text-align: center;
@@ -83,14 +101,35 @@ table.list th {
}
.bggraph {
- background-color: #faa;
white-space: nowrap;
}
+.file_input
+{
+ position: absolute;
+ width: 140px;
+ height: 26px;
+ overflow: hidden;
+}
+
+.file_input_button
+{
+ width: 140px;
+ position: absolute;
+ top: 0px;
+}
+
+.file_input_hidden
+{
+ font-size: 25px;
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ opacity: 0;
+}
</style>
<script>
-
var max_sample = 0;
Array.max = function(array) {
@@ -222,6 +261,293 @@ function restoreTable() {
document.getElementById("expand").value = FULL_VIEW;
}
}
+
+// A class to store the data to plot.
+function PData() {
+ this.xAxis = "Iteration(s)";
+ this.yAxis = "";
+ this.A = []; // Two data sets for comparison.
+ this.B = [];
+ this.avgA = []; // Avg value is plotted as a line.
+ this.avgB = [];
+ this.maxA = 0;
+ this.maxB = 0;
+ this.countA = 0; // Size of the data sets.
+ this.countB = 0;
+
+ this.setYAxis = function (str) {
+ this.yAxis = str;
+ }
+
+ this.setAvg = function (arr, cha) {
+ if (cha == 'A') {
+ var avgA = Array.avg(arr);
+ for (var i = 1; i <= this.countA; i++) {
+ this.avgA.push([i, avgA]);
+ }
+ } else if (cha == 'B') {
+ var avgB = Array.avg(arr);
+ for (var i = 1; i <= this.countB; i++) {
+ this.avgB.push([i, avgB]);
+ }
+ }
+ }
+
+ this.setMax = function (arr, cha) {
+ if (cha == 'A') {
+ this.maxA = Array.max(arr);
+ } else if (cha == 'B') {
+ this.maxB = Array.max(arr);
+ }
+ }
+
+ // Add an entry to the array.
+ this.addArr = function (val, cha) {
+ if (cha == 'A') {
+ this.countA++;
+ this.A.push([this.countA, val]);
+ } else if (cha == 'B') {
+ this.countB++;
+ this.B.push([this.countB, val]);
+ }
+ }
+
+ // Plot the graph at the specified place.
+ this.plot = function (placeholder) {
+ $.plot(placeholder,
+ [// Line A
+ {
+ data: this.A,
+ label: "A's " + this.yAxis + " in " + this.countA + " " + this.xAxis,
+ points: {
+ show: true
+ },
+ lines: {
+ show: true
+ }
+ },
+
+ // Line B
+ {
+ data: this.B,
+ label: "B's " + this.yAxis + " in " + this.countB + " " + this.xAxis,
+ points: {
+ show: true
+ },
+ lines: {
+ show: true
+ }
+ },
+
+ // Line avgA
+ {
+ data: this.avgA,
+ label: "A's avg " + this.yAxis,
+ dashes: {
+ show: true
+ }
+ },
+
+ // Line avgB
+ {
+ data: this.avgB,
+ label: "B's avg " + this.yAxis,
+ dashes: {
+ show: true
+ }
+ }],
+
+ // Axis and legend setup.
+ { xaxis: {
+ max: this.countA > this.countB ? this.countA : this.countB,
+ tickSize: 1,
+ tickDecimals: 0
+ },
+ yaxis: {
+ // Leave some space for legend.
+ max: this.maxA > this.maxB ? this.maxA * 1.5 : this.maxB * 1.5
+ },
+ legend: {
+ backgroundOpacity: 0
+ }
+ });
+ }
+}
+
+// Compare the selected metric of the two selected data sets.
+function compare() {
+ var checkboxArr = document.getElementsByName("checkboxArr");
+ var radioArr = document.getElementsByName("radioArr");
+
+ if (checkAmount(checkboxArr) != 2) {
+ alert("please select two rows to compare");
+ return;
+ }
+
+ var rowIndexArr = getSelectedIndex(checkboxArr);
+ var colIndexArr = getSelectedIndex(radioArr);
+ // To this point, it is for sure that rowIndexArr has two elements
+ // while colIndexArr has one.
+ var selectedRowA = rowIndexArr[0];
+ var selectedRowB = rowIndexArr[1];
+ var selectedCol = colIndexArr[0];
+
+ var extension = chrome.extension.getBackgroundPage();
+ var data = extension.results.data;
+ var selectedA = getSelectedResults(data,selectedRowA,selectedCol);
+ var selectedB = getSelectedResults(data,selectedRowB,selectedCol);
+ var yAxis = getMetricName(selectedCol);
+
+ // Indicate A and B on selected rows.
+ checkboxArr[selectedRowA].parentElement.firstChild.data = "A";
+ checkboxArr[selectedRowB].parentElement.firstChild.data = "B";
+
+ plot(selectedA, selectedB, yAxis);
+}
+
+// Show the comparison graph.
+function plot(A, B, axis) {
+ var plotData = new PData();
+
+ plotData.setYAxis(axis);
+ for (var i = 0; i < A.length; i++) {
+ plotData.addArr(A[i],'A');
+ }
+ for (var i = 0; i < B.length; i++) {
+ plotData.addArr(B[i],'B');
+ }
+ plotData.setAvg(A,'A');
+ plotData.setAvg(B,'B');
+ plotData.setMax(A,'A');
+ plotData.setMax(B,'B');
+
+ var placeholder = document.getElementById("placeholder");
+ placeholder.style.display = "";
+ plotData.plot(placeholder);
+}
+
+var METRIC = {"STARTLOAD": 0, "COMMITLOAD": 1, "DOCLOAD": 2, "PAINT": 3,
+ "TOTAL": 4, "REQUESTS": 5, "CONNECTS": 6, "READKB": 7,
+ "WRITEKB": 8, "READKBPS": 9, "WRITEKBPS": 10};
+
+// Retrieve the metric name from index.
+function getMetricName (index) {
+ switch (index) {
+ case METRIC.STARTLOAD:
+ return "Start Load Time";
+ case METRIC.COMMITLOAD:
+ return "Commit Load Time";
+ case METRIC.DOCLOAD:
+ return "Doc Load Time";
+ case METRIC.PAINT:
+ return "Paint Time";
+ case METRIC.TOTAL:
+ return "Total Load Time";
+ case METRIC.REQUESTS:
+ return "# Requests";
+ case METRIC.CONNECTS:
+ return "# Connects";
+ case METRIC.READKB:
+ return "Read KB";
+ case METRIC.WRITEKB:
+ return "Write KB";
+ case METRIC.READKBPS:
+ return "Read KBps";
+ case METRIC.WRITEKBPS:
+ return "Write KBps";
+ default:
+ return "";
+ }
+}
+
+// Get the results with a specific row (data set) and column (metric).
+function getSelectedResults(arr, rowIndex, colIndex) {
+ switch (colIndex) {
+ case METRIC.STARTLOAD:
+ return arr[rowIndex].startLoadResults;
+ case METRIC.COMMITLOAD:
+ return arr[rowIndex].commitLoadResults;
+ case METRIC.DOCLOAD:
+ return arr[rowIndex].docLoadResults;
+ case METRIC.PAINT:
+ return arr[rowIndex].paintResults;
+ case METRIC.TOTAL:
+ return arr[rowIndex].totalResults;
+ case METRIC.REQUESTS:
+ return arr[rowIndex].requests;
+ case METRIC.CONNECTS:
+ return arr[rowIndex].connects;
+ case METRIC.READKB:
+ return arr[rowIndex].KbytesRead;
+ case METRIC.WRITEKB:
+ return arr[rowIndex].KbytesWritten;
+ case METRIC.READKBPS:
+ return arr[rowIndex].readbpsResults;
+ case METRIC.WRITEKBPS:
+ return arr[rowIndex].writebpsResults;
+ default:
+ return undefined;
+ }
+}
+
+// Ensure only two data sets (rows) are selected.
+function checkAmount(arr) {
+ var amount = 0;
+ for (var i = 0; i < arr.length; i++) {
+ if (arr[i].checked) {
+ amount++;
+ }
+ }
+ return amount;
+}
+
+// Get the index of selected row or column.
+function getSelectedIndex(arr) {
+ var selectedArr = new Array();
+ for (var i = 0; i < arr.length; i++) {
+ if(arr[i].checked) {
+ selectedArr.push(i);
+ }
+ }
+ return selectedArr;
+}
+
+// Repaint or hide the chart.
+function updateChart(caller) {
+ var placeholder = document.getElementById("placeholder");
+ if (caller.type == "radio") {
+ // Other radio button is clicked.
+ if (placeholder.style.display == "") {
+ compare();
+ }
+ } else {
+ // Other checkbox or clearing results is clicked.
+ if (placeholder.style.display == "") {
+ placeholder.style.display = "none";
+ }
+ }
+}
+
+// Clear indicators besides checkbox.
+function clearIndicator () {
+ var checkboxArr = document.getElementsByName("checkboxArr");
+ for (var i = 0; i < checkboxArr.length; i++) {
+ checkboxArr[i].parentElement.firstChild.data = "";
+ }
+}
+
+// Enable/Disable buttons according to checkbox change.
+function checkSelected () {
+ var checkboxArr = document.getElementsByName("checkboxArr");
+ if (checkAmount(checkboxArr) !=0) {
+ document.getElementById("clearSelected").disabled = false;
+ document.getElementById("compare").disabled = false;
+ } else {
+ document.getElementById("clearSelected").disabled = true;
+ document.getElementById("compare").disabled = true;
+ }
+}
+
// Object to summarize everything
var totals = {};
@@ -230,7 +556,8 @@ function computeDisplayResults(data) {
var count = data.data.length;
for (var i = 0; i < count; i++) {
var obj = data.data[i];
- var resultList = obj.totalResults;
+ obj.displayTime = setDisplayTime(obj.timestamp);
+ var resultList = obj.totalResults;
obj.mean = Array.avg(resultList);
obj.stddev = Array.stddev(resultList);
obj.stderr = obj.stddev / Math.sqrt(obj.iterations);
@@ -239,18 +566,18 @@ function computeDisplayResults(data) {
obj.cilow = obj.mean - ci;
obj.min = Array.min(resultList);
obj.max = Array.max(resultList);
- obj.readbps = obj.bytesRead * 8 / obj.totalTime;
- obj.writebps = obj.bytesWritten * 8 / obj.totalTime;
- obj.readKB = obj.bytesRead / 1024;
- obj.writeKB = obj.bytesWritten / 1024;
+ obj.readbps = Array.avg(obj.readbpsResults);
+ obj.writebps = Array.avg(obj.writebpsResults);
+ obj.readKB = Array.avg(obj.KbytesRead);
+ obj.writeKB = Array.avg(obj.KbytesWritten);
obj.paintMean = Array.avg(obj.paintResults);
obj.startLoadMean = Array.avg(obj.startLoadResults);
obj.commitLoadMean = Array.avg(obj.commitLoadResults);
obj.docLoadMean = Array.avg(obj.docLoadResults);
- obj.displayRequests = obj.requests;
- obj.displayConnects = obj.connects;
- obj.displaySpdySessions = obj.spdySessions;
+ obj.displayRequests = Array.avg(obj.requests);
+ obj.displayConnects = Array.avg(obj.connects);
+ obj.displaySpdySessions = Array.avg(obj.spdySessions);
obj.displayDomNum = obj.domNum;
obj.displayMaxDepth = obj.maxDepth;
@@ -260,6 +587,23 @@ function computeDisplayResults(data) {
return count;
}
+// Convert timestamp to readable string.
+function setDisplayTime(ts) {
+ var year = ts.getFullYear();
+ var mon = ts.getMonth()+1;
+ var date = ts.getDate();
+ var hrs = ts.getHours();
+ var mins = ts.getMinutes();
+ var secs = ts.getSeconds();
+
+ mon = ( mon < 10 ? "0" : "" ) + mon;
+ date = ( date < 10 ? "0" : "" ) + date;
+ mins = ( mins < 10 ? "0" : "" ) + mins;
+ secs = ( secs < 10 ? "0" : "" ) + secs;
+
+ return (year + "/" + mon + "/" + date + " " + hrs + ":" + mins + ":" + secs);
+}
+
// Subtract the results from two data sets.
// This function could be smarter about what it subtracts,
// for now it just subtracts everything.
@@ -442,20 +786,51 @@ function run() {
function showConfirm() {
var r = confirm("Are you sure to clear results?");
if (r) {
- clearResults();
+ // Find out the event source element.
+ var evtSrc = window.event.srcElement;
+ if (evtSrc.value == "Clear Selected") {
+ clearSelected();
+ } else if (evtSrc.value == "Clear All") {
+ clearResults();
+ }
+ }
+}
+
+// Clear the selected results
+function clearSelected() {
+ var extension = chrome.extension.getBackgroundPage();
+ var checkboxArr = document.getElementsByName("checkboxArr");
+ var rowIndexArr = getSelectedIndex(checkboxArr);
+ var currIndex;
+ for (var i = 0; i < rowIndexArr.length; i++) {
+ currIndex = rowIndexArr[i];
+ // Update the index of the original row in the modified array.
+ currIndex -= i;
+ extension.results.data.splice(currIndex, 1);
+ document.location.reload(true);
+ updateChart(this);
+ jsinit();
}
}
-// Clear the results
+// Clear all the results
function clearResults() {
var extension = chrome.extension.getBackgroundPage();
extension.results = {};
extension.results.data = new Array();
document.getElementById("json").value = "";
document.getElementById("baseline").value = "";
+ updateChart(this);
jsinit();
}
+// Export html table into CSV format.
+function export() {
+ var checkboxArr = document.getElementsByName("checkboxArr");
+ var rowNum = checkboxArr.length + 1; // # of data rows plus total-stats row.
+ $('#t').table2CSV(rowNum);
+}
+
// Toggle display of an element
function toggle(id) {
var elt = document.getElementById(id);
@@ -481,52 +856,58 @@ Clear Connections?<input id="clearconns" type="checkbox">
Clear Cache?<input id="clearcache" type="checkbox">
Enable Spdy?<input id="enablespdy" type="checkbox">
<br>
-<span>URLs to load</span> <input type="text" id="testurl" size="100">
-<br>
-Load URLs from file<input type="file" id="files" name="files[]" multiple />
-<br>
-<form onsubmit="config();run()" style="display:inline">
+<span>URLs to load</span> <input type="text" id="testurl" size="80">
+<span class="file_input">
+<input class="file_input_button" type="button" value="Load URLs From File" />
+<input class="file_input_hidden" type="file" id="files" name="files[]" multiple />
+</span>
+<form onsubmit="config();run()">
<input type="submit" value="Run">
</form>
-<input type="button" value="Clear Results" onclick="showConfirm()">
<p>
<h1>Results</h1>
<input id="expand" type="button" value="Show More Details" onclick="expand()">
-
-<table id="t" class="list" width="100%">
+<input id="clearSelected" type="button" value="Clear Selected" disabled="true" onclick="showConfirm()">
+<input id="clearAll" type="button" value="Clear All" onclick="showConfirm()">
+<input type="button" value="Export As .csv" onclick="export()">
+<table id="t" class="sortable" width="100%">
<tr>
- <th width=150>url</th>
- <th width=50>iterations</th>
- <th width=50 >via spdy</th>
- <th width=50 style="display:none">start load mean</th>
- <th width=50 style="display:none">commit load mean</th>
- <th width=50>doc load mean</th>
- <th width=50>paint mean</th>
- <th width=50>total load mean</th>
- <th width=50>stddev</th>
- <th width=50 style="display:none">stderr</th>
- <th width=50 style="display:none">95% CI-low</th>
- <th width=50 style="display:none">95% CI-high</th>
- <th width=50 style="display:none">min</th>
- <th width=50 style="display:none">max</th>
- <th width=50 style="display:none"># Requests</th>
- <th width=50 style="display:none"># Connects</th>
- <th width=50 style="display:none"># SPDY Sessions</th>
- <th width=50 style="display:none">Read KB</th>
- <th width=50 style="display:none">Write KB</th>
- <th width=50>Read KBps</th>
- <th width=50>Write KBps</th>
- <th width=50># DOM</th>
- <th width=70 style="display:none">max DOM depth</th>
- <th width=30 style="display:none">min</th>
- <th width=30 style="display:none">avg</th>
- <th samples style="display:none"></th>
+ <th width=35 class="nobg"></th>
+ <th width=215 class="nobg">url</th>
+ <th width=110 class="nobg" style="display:none">timestamp</th>
+ <th width=50 class="nobg">iterations</th>
+ <th width=50 class="nobg">via spdy</th>
+ <th width=50 class="bg" style="display:none">start load mean</th>
+ <th width=50 class="bg" style="display:none">commit load mean</th>
+ <th width=50 class="bg">doc load mean</th>
+ <th width=50 class="bg">paint mean</th>
+ <th width=50 class="bg">total load mean</th>
+ <th width=50 class="bg">stddev</th>
+ <th width=50 class="bg" style="display:none">stderr</th>
+ <th width=50 class="bg" style="display:none">95% CI-low</th>
+ <th width=50 class="bg" style="display:none">95% CI-high</th>
+ <th width=50 class="bg" style="display:none">min</th>
+ <th width=50 class="bg" style="display:none">max</th>
+ <th width=60 class="bg" style="display:none"># Requests</th>
+ <th width=60 class="bg" style="display:none"># Connects</th>
+ <th width=50 class="bg" style="display:none"># SPDY Sessions</th>
+ <th width=50 class="bg" style="display:none">Read KB</th>
+ <th width=50 class="bg" style="display:none">Write KB</th>
+ <th width=50 class="bg">Read KBps</th>
+ <th width=50 class="bg">Write KBps</th>
+ <th width=50 class="bg"># DOM</th>
+ <th width=70 class="bg" style="display:none">max DOM depth</th>
+ <th width=30 class="bg" style="display:none">min</th>
+ <th width=30 class="bg" style="display:none">avg</th>
+ <th samples class="nobg" style="display:none">total loan time samples</th>
</tr>
<tr id="t.total" jsselect="totals">
+ <td class="avg" jseval="1"></td>
<td class="url">TOTALS <span jscontent="url"></span></td>
+ <td class="avg" style="display:none"></td>
<td class="avg" jseval="1"></td>
<td class="avg" jseval="1"></td>
<td class="avg" style="display:none"><span jseval="val = startLoadMean.toFixed(1)" jscontent="val"></span></td>
@@ -544,11 +925,20 @@ Load URLs from file<input type="file" id="files" name="files[]" multiple />
<td class="avg" jseval="1"></td>
<td class="avg" jseval="1"></td>
<td class="avg" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
<td class="data"></td>
</tr>
<tr jsselect="data">
+ <td align=right> <input type="checkbox" name="checkboxArr" onclick="updateChart(this);clearIndicator();checkSelected()"></td>
<td class="url" jseval="$width = getWidth($this.mean, this); url.length > 40 ? $suburl = url.substring(0,27) + '...' + url.substring(url.length-10, url.length) : $suburl=url"><div jsvalues=".style.width:$width" class="bggraph"><a jsvalues="href:$this.url" jscontent="$suburl"></a></div></td>
+ <td class="avg" style="display:none" jseval="val = displayTime" jscontent="val"></td>
<td class="avg" jseval="val = iterations" jscontent="val"></td>
<td class="avg" jseval="val = viaSpdy" jscontent="val"></td>
<td class="avg" style="display:none" jseval="val = startLoadMean.toFixed(1)" jscontent="val"></td>
@@ -562,9 +952,9 @@ Load URLs from file<input type="file" id="files" name="files[]" multiple />
<td class="avg" style="display:none" jseval="val = cihigh.toFixed(1)" jscontent="val"></td>
<td class="avg" style="display:none" jseval="val = min.toFixed(1)" jscontent="val"></td>
<td class="avg" style="display:none" jseval="val = max.toFixed(1)" jscontent="val"></td>
- <td class="avg" style="display:none" jseval="val = displayRequests" jscontent="val"></td>
- <td class="avg" style="display:none" jseval="val = displayConnects" jscontent="val"></td>
- <td class="avg" style="display:none" jseval="val = displaySpdySessions" jscontent="val"></td>
+ <td class="avg" style="display:none" jseval="val = displayRequests.toFixed(1)" jscontent="val"></td>
+ <td class="avg" style="display:none" jseval="val = displayConnects.toFixed(1)" jscontent="val"></td>
+ <td class="avg" style="display:none" jseval="val = displaySpdySessions.toFixed(1)" jscontent="val"></td>
<td class="avg" style="display:none" jseval="val = readKB.toFixed(1)" jscontent="val"></td>
<td class="avg" style="display:none" jseval="val = writeKB.toFixed(1)" jscontent="val"></td>
<td class="avg" jseval="val = readbps.toFixed(1)" jscontent="val"></td>
@@ -576,14 +966,45 @@ Load URLs from file<input type="file" id="files" name="files[]" multiple />
<td class="data" style="display:none"><span jsselect="totalResults"><span jscontent="$this"></span>,</span> </td>
</tr>
<tr jsdisplay="data.length == 0">
- <td colspan=11>No tests have been run yet.</td>
+ <td colspan=2>No tests have been run yet.</td>
+ </tr>
+ <tr jsdisplay="data.length > 1">
+ <td width=25 jseval="1"></td>
+ <td class="url" jseval="1"></td>
+ <td class="avg" style="display:none" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"> </td>
+ <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)" checked></td>
+ <td class="avg" jseval="1"></td>
+ <td class="avg" style="display:none" jseval="1"></td>
+ <td class="avg" style="display:none" jseval="1"></td>
+ <td class="avg" style="display:none" jseval="1"></td>
+ <td class="avg" style="display:none" jseval="1"></td>
+ <td class="avg" style="display:none" jseval="1"></td>
+ <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ <td class="avg" style="display:none" jseval="1"></td>
+ <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ <td class="avg" style="display:none"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ <td class="avg"><input name="radioArr" type="radio" onclick="updateChart(this)"></td>
+ </tr>
+ <tr jsdisplay="data.length > 1">
+ <td> <input id="compare" type="button" value="Compare" disabled="true" onclick="compare()"></td>
</tr>
</table>
<hr>
+<center>
+<div id="placeholder" style="width:430px;height:230px;display:none">graph place</div>
+</center>
<span onclick="toggle('json')">JSON data</span><br>
-<textarea style="display: none" type=text id=json rows=10 cols=50></textarea><p>
+<textarea style="display:none" type=text id=json rows=10 cols=50></textarea><p>
<span onclick="toggle('baseline')">COMPARE to</span><br>
-<textarea style="display: none" type=text id=baseline rows=10 cols=50
+<textarea style="display:none" type=text id=baseline rows=10 cols=50
onchange="jsinit()"></textarea><p>
</body>
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/util/sorttable.js b/chrome/common/extensions/docs/examples/extensions/benchmark/util/sorttable.js
new file mode 100644
index 0000000..5583053
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/util/sorttable.js
@@ -0,0 +1,489 @@
+/*
+ SortTable
+ version 2
+ 7th April 2007
+ Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
+
+ Instructions:
+ Download this file
+ Add <script src="sorttable.js"></script> to your HTML
+ Add class="sortable" to any table you'd like to make sortable
+ Click on the headers to sort
+
+ Thanks to many, many people for contributions and suggestions.
+ Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
+ This basically means: do what you want with it.
+*/
+
+/*
+Changes by jning:
+-Specify which coloumns to sort or not by changing index in makeSortable().
+-To avoid including the non-data rows (e.g., radio buttions) into sorting,
+ add index and row handling (deletion and appending) in makeSortable() and
+ reverse().
+-Remove the init parts for other browsers.
+*/
+
+var stIsIE = /*@cc_on!@*/false;
+
+sorttable = {
+ init: function() {
+ // quit if this function has already been called
+ if (arguments.callee.done) return;
+ // flag this function so we don't do the same thing twice
+ arguments.callee.done = true;
+ // kill the timer
+ if (_timer) clearInterval(_timer);
+
+ if (!document.createElement || !document.getElementsByTagName) return;
+
+ sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
+
+ forEach(document.getElementsByTagName('table'), function(table) {
+ if (table.className.search(/\bsortable\b/) != -1) {
+ sorttable.makeSortable(table);
+ }
+ });
+
+ },
+
+ makeSortable: function(table) {
+ if (table.getElementsByTagName('thead').length == 0) {
+ // table doesn't have a tHead. Since it should have, create one and
+ // put the first table row in it.
+ the = document.createElement('thead');
+ the.appendChild(table.rows[0]);
+ table.insertBefore(the,table.firstChild);
+ }
+ // Safari doesn't support table.tHead, sigh
+ if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
+
+ if (table.tHead.rows.length != 1) return; // can't cope with two header rows
+
+ // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
+ // "total" rows, for example). This is B&R, since what you're supposed
+ // to do is put them in a tfoot. So, if there are sortbottom rows,
+ // for backwards compatibility, move them to tfoot (creating it if needed).
+ sortbottomrows = [];
+ for (var i=0; i<table.rows.length; i++) {
+ if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
+ sortbottomrows[sortbottomrows.length] = table.rows[i];
+ }
+ }
+ if (sortbottomrows) {
+ if (table.tFoot == null) {
+ // table doesn't have a tfoot. Create one.
+ tfo = document.createElement('tfoot');
+ table.appendChild(tfo);
+ }
+ for (var i=0; i<sortbottomrows.length; i++) {
+ tfo.appendChild(sortbottomrows[i]);
+ }
+ delete sortbottomrows;
+ }
+
+ // work through each column and calculate its type
+ headrow = table.tHead.rows[0].cells;
+ for (var i=5; i<headrow.length-1; i++) {
+ // manually override the type with a sorttable_type attribute
+ if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col
+ mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
+ if (mtch) { override = mtch[1]; }
+ if (mtch && typeof sorttable["sort_"+override] == 'function') {
+ headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
+ } else {
+ headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
+ }
+ // make it clickable to sort
+ headrow[i].sorttable_columnindex = i;
+ headrow[i].sorttable_tbody = table.tBodies[0];
+ dean_addEvent(headrow[i],"click", function(e) {
+
+ if (this.className.search(/\bsorttable_sorted\b/) != -1) {
+ // if we're already sorted by this column, just
+ // reverse the table, which is quicker
+ sorttable.reverse(this.sorttable_tbody);
+ this.className = this.className.replace('sorttable_sorted',
+ 'sorttable_sorted_reverse');
+ this.removeChild(document.getElementById('sorttable_sortfwdind'));
+ sortrevind = document.createElement('span');
+ sortrevind.id = "sorttable_sortrevind";
+ sortrevind.innerHTML = stIsIE ? '&nbsp<font face="webdings">5</font>' : '&nbsp;&#x25B4;';
+ this.appendChild(sortrevind);
+ return;
+ }
+ if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
+ // if we're already sorted by this column in reverse, just
+ // re-reverse the table, which is quicker
+ sorttable.reverse(this.sorttable_tbody);
+ this.className = this.className.replace('sorttable_sorted_reverse',
+ 'sorttable_sorted');
+ this.removeChild(document.getElementById('sorttable_sortrevind'));
+ sortfwdind = document.createElement('span');
+ sortfwdind.id = "sorttable_sortfwdind";
+ sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
+ this.appendChild(sortfwdind);
+ return;
+ }
+
+ // remove sorttable_sorted classes
+ theadrow = this.parentNode;
+ forEach(theadrow.childNodes, function(cell) {
+ if (cell.nodeType == 1) { // an element
+ cell.className = cell.className.replace('sorttable_sorted_reverse','');
+ cell.className = cell.className.replace('sorttable_sorted','');
+ }
+ });
+ sortfwdind = document.getElementById('sorttable_sortfwdind');
+ if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
+ sortrevind = document.getElementById('sorttable_sortrevind');
+ if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
+
+ this.className += ' sorttable_sorted';
+ sortfwdind = document.createElement('span');
+ sortfwdind.id = "sorttable_sortfwdind";
+ sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
+ this.appendChild(sortfwdind);
+
+ // build an array to sort. This is a Schwartzian transform thing,
+ // i.e., we "decorate" each row with the actual sort key,
+ // sort based on the sort keys, and then put the rows back in order
+ // which is a lot faster because you only do getInnerText once per row
+ row_array = [];
+ col = this.sorttable_columnindex;
+ rows = this.sorttable_tbody.rows;
+ for (var j=1; j<rows.length-3; j++) {
+ row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
+ }
+ /* If you want a stable sort, uncomment the following line */
+ sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
+ /* and comment out this one */
+ //row_array.sort(this.sorttable_sortfunction);
+
+ tb = this.sorttable_tbody;
+ var noTestRow = tb.rows[tb.rows.length-3];
+ var radioRow = tb.rows[tb.rows.length-2];
+ var compareRow = tb.rows[tb.rows.length-1];
+ tb.deleteRow(tb.rows.length-1);
+ tb.deleteRow(tb.rows.length-1);
+ tb.deleteRow(tb.rows.length-1);
+ for (var j=0; j<row_array.length; j++) {
+ tb.appendChild(row_array[j][1]);
+ }
+ tb.appendChild(noTestRow);
+ tb.appendChild(radioRow);
+ tb.appendChild(compareRow);
+ delete row_array;
+ delete noTestRow;
+ delete radioRow;
+ delete compareRow;
+ });
+ }
+ }
+ },
+
+ guessType: function(table, column) {
+ // guess the type of a column based on its first non-blank row
+ sortfn = sorttable.sort_numeric;
+ for (var i=0; i<table.tBodies[0].rows.length-3; i++) {
+ text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
+ if (text != '') {
+ if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) {
+ return sorttable.sort_numeric;
+ }
+ // check for a date: dd/mm/yyyy or dd/mm/yy
+ // can have / or . or - as separator
+ // can be mm/dd as well
+ possdate = text.match(sorttable.DATE_RE)
+ if (possdate) {
+ // looks like a date
+ first = parseInt(possdate[1]);
+ second = parseInt(possdate[2]);
+ if (first > 12) {
+ // definitely dd/mm
+ return sorttable.sort_ddmm;
+ } else if (second > 12) {
+ return sorttable.sort_mmdd;
+ } else {
+ // looks like a date, but we can't tell which, so assume
+ // that it's dd/mm (English imperialism!) and keep looking
+ sortfn = sorttable.sort_ddmm;
+ }
+ }
+ }
+ }
+ return sortfn;
+ },
+
+ getInnerText: function(node) {
+ // gets the text we want to use for sorting for a cell.
+ // strips leading and trailing whitespace.
+ // this is *not* a generic getInnerText function; it's special to sorttable.
+ // for example, you can override the cell text with a customkey attribute.
+ // it also gets .value for <input> fields.
+
+ hasInputs = (typeof node.getElementsByTagName == 'function') &&
+ node.getElementsByTagName('input').length;
+
+ if (node.getAttribute("sorttable_customkey") != null) {
+ return node.getAttribute("sorttable_customkey");
+ }
+ else if (typeof node.textContent != 'undefined' && !hasInputs) {
+ return node.textContent.replace(/^\s+|\s+$/g, '');
+ }
+ else if (typeof node.innerText != 'undefined' && !hasInputs) {
+ return node.innerText.replace(/^\s+|\s+$/g, '');
+ }
+ else if (typeof node.text != 'undefined' && !hasInputs) {
+ return node.text.replace(/^\s+|\s+$/g, '');
+ }
+ else {
+ switch (node.nodeType) {
+ case 3:
+ if (node.nodeName.toLowerCase() == 'input') {
+ return node.value.replace(/^\s+|\s+$/g, '');
+ }
+ case 4:
+ return node.nodeValue.replace(/^\s+|\s+$/g, '');
+ break;
+ case 1:
+ case 11:
+ var innerText = '';
+ for (var i = 0; i < node.childNodes.length; i++) {
+ innerText += sorttable.getInnerText(node.childNodes[i]);
+ }
+ return innerText.replace(/^\s+|\s+$/g, '');
+ break;
+ default:
+ return '';
+ }
+ }
+ },
+
+ reverse: function(tbody) {
+ // reverse the rows in a tbody
+ newrows = [];
+ for (var i=0; i<tbody.rows.length; i++) {
+ newrows[newrows.length] = tbody.rows[i];
+ }
+ tbody.appendChild(newrows[0]);
+ for (var i=newrows.length-4; i>0; i--) {
+ tbody.appendChild(newrows[i]);
+ }
+ tbody.appendChild(newrows[newrows.length-3]);
+ tbody.appendChild(newrows[newrows.length-2]);
+ tbody.appendChild(newrows[newrows.length-1]);
+ delete newrows;
+ },
+
+ /* sort functions
+ each sort function takes two parameters, a and b
+ you are comparing a[0] and b[0] */
+ sort_numeric: function(a,b) {
+ aa = parseFloat(a[0].replace(/[^0-9.-]/g,''));
+ if (isNaN(aa)) aa = 0;
+ bb = parseFloat(b[0].replace(/[^0-9.-]/g,''));
+ if (isNaN(bb)) bb = 0;
+ return aa-bb;
+ },
+ sort_alpha: function(a,b) {
+ if (a[0]==b[0]) return 0;
+ if (a[0]<b[0]) return -1;
+ return 1;
+ },
+ sort_ddmm: function(a,b) {
+ mtch = a[0].match(sorttable.DATE_RE);
+ y = mtch[3]; m = mtch[2]; d = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt1 = y+m+d;
+ mtch = b[0].match(sorttable.DATE_RE);
+ y = mtch[3]; m = mtch[2]; d = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt2 = y+m+d;
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+ },
+ sort_mmdd: function(a,b) {
+ mtch = a[0].match(sorttable.DATE_RE);
+ y = mtch[3]; d = mtch[2]; m = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt1 = y+m+d;
+ mtch = b[0].match(sorttable.DATE_RE);
+ y = mtch[3]; d = mtch[2]; m = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt2 = y+m+d;
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+ },
+
+ shaker_sort: function(list, comp_func) {
+ // A stable sort function to allow multi-level sorting of data
+ // see: http://en.wikipedia.org/wiki/Cocktail_sort
+ // thanks to Joseph Nahmias
+ var b = 0;
+ var t = list.length - 1;
+ var swap = true;
+
+ while(swap) {
+ swap = false;
+ for(var i = b; i < t; ++i) {
+ if ( comp_func(list[i], list[i+1]) > 0 ) {
+ var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
+ swap = true;
+ }
+ } // for
+ t--;
+
+ if (!swap) break;
+
+ for(var i = t; i > b; --i) {
+ if ( comp_func(list[i], list[i-1]) < 0 ) {
+ var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
+ swap = true;
+ }
+ } // for
+ b++;
+
+ } // while(swap)
+ }
+}
+
+/* ******************************************************************
+ Supporting functions: bundled here to avoid depending on a library
+ ****************************************************************** */
+
+// Dean Edwards/Matthias Miller/John Resig
+
+/* for other browsers */
+window.onload = sorttable.init;
+
+// written by Dean Edwards, 2005
+// with input from Tino Zijdel, Matthias Miller, Diego Perini
+
+// http://dean.edwards.name/weblog/2005/10/add-event/
+
+function dean_addEvent(element, type, handler) {
+ if (element.addEventListener) {
+ element.addEventListener(type, handler, false);
+ } else {
+ // assign each event handler a unique ID
+ if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
+ // create a hash table of event types for the element
+ if (!element.events) element.events = {};
+ // create a hash table of event handlers for each element/event pair
+ var handlers = element.events[type];
+ if (!handlers) {
+ handlers = element.events[type] = {};
+ // store the existing event handler (if there is one)
+ if (element["on" + type]) {
+ handlers[0] = element["on" + type];
+ }
+ }
+ // store the event handler in the hash table
+ handlers[handler.$$guid] = handler;
+ // assign a global event handler to do all the work
+ element["on" + type] = handleEvent;
+ }
+};
+// a counter used to create unique IDs
+dean_addEvent.guid = 1;
+
+function removeEvent(element, type, handler) {
+ if (element.removeEventListener) {
+ element.removeEventListener(type, handler, false);
+ } else {
+ // delete the event handler from the hash table
+ if (element.events && element.events[type]) {
+ delete element.events[type][handler.$$guid];
+ }
+ }
+};
+
+function handleEvent(event) {
+ var returnValue = true;
+ // grab the event object (IE uses a global event object)
+ event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
+ // get a reference to the hash table of event handlers
+ var handlers = this.events[event.type];
+ // execute each event handler
+ for (var i in handlers) {
+ this.$$handleEvent = handlers[i];
+ if (this.$$handleEvent(event) === false) {
+ returnValue = false;
+ }
+ }
+ return returnValue;
+};
+
+function fixEvent(event) {
+ // add W3C standard event methods
+ event.preventDefault = fixEvent.preventDefault;
+ event.stopPropagation = fixEvent.stopPropagation;
+ return event;
+};
+fixEvent.preventDefault = function() {
+ this.returnValue = false;
+};
+fixEvent.stopPropagation = function() {
+ this.cancelBubble = true;
+}
+
+// Dean's forEach: http://dean.edwards.name/base/forEach.js
+/*
+ forEach, version 1.0
+ Copyright 2006, Dean Edwards
+ License: http://www.opensource.org/licenses/mit-license.php
+*/
+
+// array-like enumeration
+if (!Array.forEach) { // mozilla already supports this
+ Array.forEach = function(array, block, context) {
+ for (var i = 0; i < array.length; i++) {
+ block.call(context, array[i], i, array);
+ }
+ };
+}
+
+// generic enumeration
+Function.prototype.forEach = function(object, block, context) {
+ for (var key in object) {
+ if (typeof this.prototype[key] == "undefined") {
+ block.call(context, object[key], key, object);
+ }
+ }
+};
+
+// character enumeration
+String.forEach = function(string, block, context) {
+ Array.forEach(string.split(""), function(chr, index) {
+ block.call(context, chr, index, string);
+ });
+};
+
+// globally resolve forEach enumeration
+var forEach = function(object, block, context) {
+ if (object) {
+ var resolve = Object; // default
+ if (object instanceof Function) {
+ // functions have a "length" property
+ resolve = Function;
+ } else if (object.forEach instanceof Function) {
+ // the object implements a custom forEach method so use that
+ object.forEach(block, context);
+ return;
+ } else if (typeof object == "string") {
+ // the object is a string
+ resolve = String;
+ } else if (typeof object.length == "number") {
+ // the object is array-like
+ resolve = Array;
+ }
+ resolve.forEach(object, block, context);
+ }
+};
diff --git a/chrome/common/extensions/docs/examples/extensions/benchmark/util/table2CSV.js b/chrome/common/extensions/docs/examples/extensions/benchmark/util/table2CSV.js
new file mode 100644
index 0000000..04a5166
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/extensions/benchmark/util/table2CSV.js
@@ -0,0 +1,90 @@
+/*
+This is a small JQuery utility to export HTML table as CSV file.
+
+The author is Kunal Babre and the original script can be found in
+http://www.kunalbabre.com/projects/table2CSV.php. Permissions are
+granted by the author to make changes and redistribute.
+
+Changes made by jning: To avoid exporting the textbox, radio buttons and etc.
+in the table, the parameters rowNum and index in $().find().each() or
+$().filter().find.each() help to ignore non-data cells.
+*/
+
+jQuery.fn.table2CSV = function(rowNum, options) {
+ var options = jQuery.extend({
+ separator: ',',
+ header: [],
+ delivery: 'popup' // popup, value
+ },
+ options);
+
+ var csvData = [];
+ var headerArr = [];
+ var el = this;
+
+ //header
+ var numCols = options.header.length;
+ var tmpRow = []; // construct header avalible array
+
+ if (numCols > 0) {
+ for (var i = 0; i < numCols; i++) {
+ tmpRow[tmpRow.length] = formatData(options.header[i]);
+ }
+ } else {
+ $(el).filter(':visible').find('th').each(function(index) {
+ if (index > 0 && $(this).css('display') != 'none')
+ tmpRow[tmpRow.length] = formatData($(this).html());
+ });
+ }
+
+ row2CSV(tmpRow);
+
+ // actual data
+ $(el).find('tr').each(function(index) {
+ if (index < rowNum + 1) {
+ var tmpRow = [];
+ $(this).filter(':visible').find('td').each(function(index) {
+ if (index > 0 && $(this).css('display') != 'none')
+ tmpRow[tmpRow.length] = formatData($(this).html());
+ });
+ row2CSV(tmpRow);
+ }
+ });
+ if (options.delivery == 'popup') {
+ var mydata = csvData.join('\n');
+ return popup(mydata);
+ } else {
+ var mydata = csvData.join('\n');
+ return mydata;
+ }
+
+ function row2CSV(tmpRow) {
+ var tmp = tmpRow.join('') // to remove any blank rows
+ // alert(tmp);
+ if (tmpRow.length > 0 && tmp != '') {
+ var mystr = tmpRow.join(options.separator);
+ csvData[csvData.length] = mystr;
+ }
+ }
+ function formatData(input) {
+ // replace " with “
+ var regexp = new RegExp(/["]/g);
+ var output = input.replace(regexp, "“");
+ //HTML
+ var regexp = new RegExp(/\<[^\<]+\>/g);
+ var output = output.replace(regexp, "");
+ if (output == "") return '';
+ return '"' + output + '"';
+ }
+ function popup(data) {
+ var generator = window.open('', 'csv', 'height=400,width=600');
+ generator.document.write('<html><head><title>CSV</title>');
+ generator.document.write('</head><body >');
+ generator.document.write('<textArea cols=70 rows=15 wrap="off" >');
+ generator.document.write(data);
+ generator.document.write('</textArea>');
+ generator.document.write('</body></html>');
+ generator.document.close();
+ return true;
+ }
+};
diff --git a/chrome/common/extensions/docs/experimental.clipboard.html b/chrome/common/extensions/docs/experimental.clipboard.html
index 0bf145d..dc9d20b 100644
--- a/chrome/common/extensions/docs/experimental.clipboard.html
+++ b/chrome/common/extensions/docs/experimental.clipboard.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.clipboard - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.contextMenus.html b/chrome/common/extensions/docs/experimental.contextMenus.html
index db22bb4..5c11ce2 100644
--- a/chrome/common/extensions/docs/experimental.contextMenus.html
+++ b/chrome/common/extensions/docs/experimental.contextMenus.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>experimental.chrome.contextMenus - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.cookies.html b/chrome/common/extensions/docs/experimental.cookies.html
index 1eaeee9..b57ea7f 100644
--- a/chrome/common/extensions/docs/experimental.cookies.html
+++ b/chrome/common/extensions/docs/experimental.cookies.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>experimental.chrome.cookies - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.history.html b/chrome/common/extensions/docs/experimental.history.html
index 5b1b412..7a2deda 100644
--- a/chrome/common/extensions/docs/experimental.history.html
+++ b/chrome/common/extensions/docs/experimental.history.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>experimental.chrome.history - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.html b/chrome/common/extensions/docs/experimental.html
index 08480af..3fe2e15 100644
--- a/chrome/common/extensions/docs/experimental.html
+++ b/chrome/common/extensions/docs/experimental.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.* APIs - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.idle.html b/chrome/common/extensions/docs/experimental.idle.html
index d7b2d80..7712706 100644
--- a/chrome/common/extensions/docs/experimental.idle.html
+++ b/chrome/common/extensions/docs/experimental.idle.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>experimental.chrome.idle - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.infobars.html b/chrome/common/extensions/docs/experimental.infobars.html
index 97d859d..0c9295d 100644
--- a/chrome/common/extensions/docs/experimental.infobars.html
+++ b/chrome/common/extensions/docs/experimental.infobars.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.infobars - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.omnibox.html b/chrome/common/extensions/docs/experimental.omnibox.html
index 995f838..1a668ed 100644
--- a/chrome/common/extensions/docs/experimental.omnibox.html
+++ b/chrome/common/extensions/docs/experimental.omnibox.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.omnibox - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -1259,7 +1263,7 @@ You can find samples of this API on the
</div>
</div>
- </dl>
+ </dl>
</div>
</dd>
diff --git a/chrome/common/extensions/docs/experimental.processes.html b/chrome/common/extensions/docs/experimental.processes.html
index 801ff1e..a5e3b05 100644
--- a/chrome/common/extensions/docs/experimental.processes.html
+++ b/chrome/common/extensions/docs/experimental.processes.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.processes - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.proxy.html b/chrome/common/extensions/docs/experimental.proxy.html
index 57d48f5..3d27695 100644
--- a/chrome/common/extensions/docs/experimental.proxy.html
+++ b/chrome/common/extensions/docs/experimental.proxy.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.proxy - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.sidebar.html b/chrome/common/extensions/docs/experimental.sidebar.html
index eb9493b..35b757b 100644
--- a/chrome/common/extensions/docs/experimental.sidebar.html
+++ b/chrome/common/extensions/docs/experimental.sidebar.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.sidebar - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.webNavigation.html b/chrome/common/extensions/docs/experimental.webNavigation.html
index 8ab76fc..aebd5ca 100644
--- a/chrome/common/extensions/docs/experimental.webNavigation.html
+++ b/chrome/common/extensions/docs/experimental.webNavigation.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.webNavigation - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/experimental.webRequest.html b/chrome/common/extensions/docs/experimental.webRequest.html
index 9615bcc..0541584 100644
--- a/chrome/common/extensions/docs/experimental.webRequest.html
+++ b/chrome/common/extensions/docs/experimental.webRequest.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.experimental.webRequest - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/extension.html b/chrome/common/extensions/docs/extension.html
index b361568..36c768f 100644
--- a/chrome/common/extensions/docs/extension.html
+++ b/chrome/common/extensions/docs/extension.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.extension - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -1891,7 +1895,7 @@ For details, see
</div>
</div>
- </dl>
+ </dl>
</div>
</dd>
diff --git a/chrome/common/extensions/docs/external_extensions.html b/chrome/common/extensions/docs/external_extensions.html
index 6bf9e4f..d3f18ad 100644
--- a/chrome/common/extensions/docs/external_extensions.html
+++ b/chrome/common/extensions/docs/external_extensions.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Other Deployment Options - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/faq.html b/chrome/common/extensions/docs/faq.html
index 94ec93b..ea4af3a 100644
--- a/chrome/common/extensions/docs/faq.html
+++ b/chrome/common/extensions/docs/faq.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Frequently Asked Questions - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -376,12 +380,21 @@ try the
<p>
As long as you are using a version of Google Chrome that supports
extensions, you already have everything you need to start writing an
- extension of your own. Select <b>Extensions</b> from the Tools menu
- <img style="vertical-align: middle; margin:0; padding:0" src="images/toolsmenu.gif"> (or from
- the Window menu on Mac) and click <b>Developer Mode</b>. From there, you can load
- an unpacked directory of files as if it were a packaged extension, reload
- extensions, and more. For a complete tutorial, please view
- <a href="http://code.google.com/chrome/extensions/getstarted.html">this getting started guide</a>.
+ extension of your own.
+ You can start by turning on Developer mode.
+ </p>
+
+ <p>
+ Click the wrench icon
+ <img src="images/toolsmenu.gif" height="29" width="29" alt="" class="nomargin">
+ and select <b>Extensions</b> from the <b>Tools</b> menu
+ (or from the <b>Window</b> menu on Mac).
+ If there's a "+" next to "Developer mode",
+ click the "+" so it turns into a "-".
+ Now you can reload extensions,
+ load an unpacked directory of files as if it were a packaged extension,
+ and more. For a complete tutorial, see
+ <a href="http://code.google.com/chrome/extensions/getstarted.html">Getting Started</a>.
</p>
<h3 id="faq-dev-02">Can I make cross-domain Ajax requests in an extension?</h3>
@@ -679,7 +692,9 @@ win,stable,#.#.###.#,#.#.###.#</pre>
to the ticket you starred or opened. This will make it easier for others
with the same request to find the correct ticket.
</li>
-</ol></div>
+</ol>
+
+</div>
<!-- API PAGE -->
<div class="apiPage" style="display: none; ">
diff --git a/chrome/common/extensions/docs/getstarted.html b/chrome/common/extensions/docs/getstarted.html
index a3a10fc..5590e32 100644
--- a/chrome/common/extensions/docs/getstarted.html
+++ b/chrome/common/extensions/docs/getstarted.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Tutorial: Getting Started (Hello, World!) - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -358,14 +362,12 @@ to the toolbar of Google Chrome.
</li>
<li id="load-ext"> Load the extension.
<ol type="a">
- <li>
+ <li style="margin-top:0">
Bring up the extensions management page
- by clicking the Tools menu
- <img src="images/toolsmenu.gif" width="43" height="34" alt="" align="absmiddle" style="margin:0; padding:0">
- (or the Window menu on Mac)
- and choosing <b>Extensions</b>.
- (If you're using version 6 or later,
- choose <b>Tools &gt; Extensions</b>.)
+ by clicking the wrench icon
+ <img src="images/toolsmenu.gif" width="29" height="29" alt="" style="margin-top:0">
+ and choosing <b>Tools &gt; Extensions</b>.
+ (On Mac, use <b>Window &gt; Extensions</b>.)
</li>
<li>
diff --git a/chrome/common/extensions/docs/history.html b/chrome/common/extensions/docs/history.html
index 41b93ab..5fed0af 100644
--- a/chrome/common/extensions/docs/history.html
+++ b/chrome/common/extensions/docs/history.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>chrome.history - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/hosting.html b/chrome/common/extensions/docs/hosting.html
index 20267e7..55c0178 100644
--- a/chrome/common/extensions/docs/hosting.html
+++ b/chrome/common/extensions/docs/hosting.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Hosting - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/i18n-messages.html b/chrome/common/extensions/docs/i18n-messages.html
index 7ff4c33..823bfc3 100644
--- a/chrome/common/extensions/docs/i18n-messages.html
+++ b/chrome/common/extensions/docs/i18n-messages.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Formats: Locale-Specific Messages - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/i18n.html b/chrome/common/extensions/docs/i18n.html
index 6809923..b33c856 100644
--- a/chrome/common/extensions/docs/i18n.html
+++ b/chrome/common/extensions/docs/i18n.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Internationalization (i18n) - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -767,7 +771,7 @@ Here's how to change the locale using the UI on Google Chrome for Windows:
</p>
<ol>
- <li> Tools menu (wrench) &gt; <b>Options</b> </li>
+ <li> Wrench icon &gt; <b>Options</b> </li>
<li> Choose the <b>Under the Hood</b> tab </li>
<li> Scroll down to <b>Web Content</b> </li>
<li> Click <b>Change font and language settings</b> </li>
diff --git a/chrome/common/extensions/docs/idle.html b/chrome/common/extensions/docs/idle.html
index 2fd5dd8..0d6988c 100644
--- a/chrome/common/extensions/docs/idle.html
+++ b/chrome/common/extensions/docs/idle.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Idle - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/images/toggle_sprite.png b/chrome/common/extensions/docs/images/toggle_sprite.png
new file mode 100644
index 0000000..a91c2d4
--- /dev/null
+++ b/chrome/common/extensions/docs/images/toggle_sprite.png
Binary files differ
diff --git a/chrome/common/extensions/docs/images/toolsmenu.gif b/chrome/common/extensions/docs/images/toolsmenu.gif
index d6afcab..1b0b1e5 100644
--- a/chrome/common/extensions/docs/images/toolsmenu.gif
+++ b/chrome/common/extensions/docs/images/toolsmenu.gif
Binary files differ
diff --git a/chrome/common/extensions/docs/index.html b/chrome/common/extensions/docs/index.html
index 826d74b..12e3114 100644
--- a/chrome/common/extensions/docs/index.html
+++ b/chrome/common/extensions/docs/index.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/js/sidebar.js b/chrome/common/extensions/docs/js/sidebar.js
new file mode 100644
index 0000000..51d9292
--- /dev/null
+++ b/chrome/common/extensions/docs/js/sidebar.js
@@ -0,0 +1,84 @@
+/**
+ * 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.
+ */
+
+var TEXT_NODE = 3; // Text nodes have nodeType of 3.
+
+/**
+ * Toggles the display of nodes given the status of their associated controls.
+ *
+ * For each node passed to this function, check to see if a toggle has been
+ * inserted into the node's parent. If yes, change the state of the toggle and
+ * hide/reveal the node as needed.
+ *
+ * @param {NodeList|Node|Array.<Node>} Nodes to operate on.
+ */
+function toggleList(list) {
+ if (typeof list.length != 'number') {
+ list = Array(list);
+ }
+
+ for (var i = 0; i < list.length; i++) {
+ var toggle = list[i].parentNode &&
+ list[i].parentNode.firstChild;
+ if (toggle && toggle.className.substring(0, 6) == 'toggle') {
+ var visible = toggle.className == 'toggle';
+ list[i].style.display = visible ? 'block' : 'none';
+ toggle.className = visible ? 'toggle selected' : 'toggle';
+ }
+ }
+};
+
+/**
+ * Reveals the hidden ancestor of the passed node, adjusts toggles as needed.
+ *
+ * @param {Node} node The node whose ancestor is a hidden toggleable element.
+ */
+function revealAncestor(node) {
+ while (node.parentNode) {
+ if (node.style.display == 'none') {
+ toggleList(node);
+ break;
+ }
+ node = node.parentNode;
+ }
+};
+
+/**
+ * Adds toggle controls to the sidebar list.
+ *
+ * Controls are inserted as the first children of list items in the sidebar
+ * which contain only text (not a link). Handlers are set up so that when a
+ * toggle control is clicked, any <ul> elements who are siblings of the control
+ * are hidden/revealed as appropriate given the control's state.
+ *
+ * If a list item possesses the class "leftNavSelected" its ancestor <ul> is
+ * revealed by default (it represents the current page).
+ */
+function initToggles() {
+ var toc = document.getElementById('gc-toc');
+ var items = toc.getElementsByTagName('li');
+ var selectedNode = null;
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (item.className == 'leftNavSelected') {
+ selectedNode = item;
+ } else if (item.firstChild &&
+ item.firstChild.nodeType == TEXT_NODE) {
+ // Only assign toggles to text nodes in the sidebar.
+ var a = document.createElement('a');
+ a.className = 'toggle selected';
+ a.appendChild(document.createTextNode(' '));
+ a.onclick = function() {
+ toggleList(this.parentNode.getElementsByTagName('ul'));
+ };
+ item.insertBefore(a, item.firstChild);
+ toggleList(item.getElementsByTagName('ul'));
+ }
+ }
+ if (selectedNode) {
+ revealAncestor(selectedNode);
+ }
+};
diff --git a/chrome/common/extensions/docs/management.html b/chrome/common/extensions/docs/management.html
index 8fb7add..2792019 100644
--- a/chrome/common/extensions/docs/management.html
+++ b/chrome/common/extensions/docs/management.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Management - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -234,10 +238,10 @@
<div id="toc">
<h2>Contents</h2>
<ol>
- <li style="display: none; ">
- <a>h2Name</a>
+ <li>
+ <a href="#manifest">Manifest</a>
<ol>
- <li>
+ <li style="display: none; ">
<a>h3Name</a>
</li>
</ol>
@@ -257,6 +261,8 @@
<a href="#methods">Methods</a>
<ol>
<li>
+ <a href="#method-get">get</a>
+ </li><li>
<a href="#method-getAll">getAll</a>
</li><li>
<a href="#method-launchApp">launchApp</a>
@@ -304,10 +310,27 @@
<!-- STATIC CONTENT PLACEHOLDER -->
<div id="static"><div id="pageData-name" class="pageData">Management</div>
+
<!-- BEGIN AUTHORED CONTENT -->
<p id="classSummary">
The <code>chrome.management</code> module provides ways to manage the list of extensions/apps that are installed and running. It is particularly useful for extensions that <a href="override.html">override</a> the built-in New Tab page.
</p>
+
+<h2 id="manifest">Manifest</h2>
+
+<p>You must declare the "management" permission
+in the <a href="manifest.html">extension manifest</a>
+to use the management API.
+For example:</p>
+<pre>{
+ "name": "My extension",
+ ...
+ <b>"permissions": [
+ "management"
+ ]</b>,
+ ...
+}</pre>
+
<!-- END AUTHORED CONTENT -->
</div>
@@ -341,6 +364,243 @@ The <code>chrome.management</code> module provides ways to manage the list of ex
<!-- iterates over all functions -->
<div class="apiItem">
+ <a name="method-get"></a> <!-- method-anchor -->
+ <h4>get</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.management.get</span>(<span class="null"><span style="display: none; ">, </span><span>string</span>
+ <var><span>id</span></var></span><span class="optional"><span>, </span><span>function</span>
+ <var><span>callback</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Return information about the installed extension with the given ID.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>id</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The ID from an item of <a href="management.html#type-ExtensionInfo">ExtensionInfo</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>callback</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div>
+ <div>
+ <h4>Callback function</h4>
+ <p style="display: none; ">
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>ExtensionInfo result</span>) <span class="subdued">{...}</span>;</pre>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>result</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a href="management.html#type-ExtensionInfo">ExtensionInfo</a>
+ </span>
+ <span style="display: none; ">
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
<a name="method-getAll"></a> <!-- method-anchor -->
<h4>getAll</h4>
diff --git a/chrome/common/extensions/docs/manifest.html b/chrome/common/extensions/docs/manifest.html
index d8bd4f4..b593f31 100644
--- a/chrome/common/extensions/docs/manifest.html
+++ b/chrome/common/extensions/docs/manifest.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Formats: Manifest Files - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -245,11 +249,15 @@
<a href="#H2-1">Field details</a>
<ol>
<li>
+ <a href="#default_locale">default_locale</a>
+ </li><li>
<a href="#description">description</a>
</li><li>
+ <a href="#homepage_url">homepage_url</a>
+ </li><li>
<a href="#icons">icons</a>
</li><li>
- <a href="#default_locale">default_locale</a>
+ <a href="#incognito">incognito</a>
</li><li>
<a href="#key">key</a>
</li><li>
@@ -260,8 +268,6 @@
<a href="#permissions">permissions</a>
</li><li>
<a href="#version">version</a>
- </li><li>
- <a href="#incognito">incognito</a>
</li>
</ol>
</li>
@@ -350,13 +356,14 @@ are <b>name</b> and <b>version</b>.
"<a href="background_pages.html">background_page</a>": "<em>aFile</em>.html",
"<a href="override.html">chrome_url_overrides</a>": {...},
"<a href="content_scripts.html">content_scripts</a>": [...],
+ "<a href="#homepage_url">homepage_url</a>": "http://<em>path/to/homepage</em>",
+ "<a href="#incognito">incognito</a>": "spanning" <em>or</em> "split",
"<a href="#key">key</a>": "<em>publicKey</em>",
"<a href="#minimum_chrome_version">minimum_chrome_version</a>": "<em>versionString</em>",
"<a href="options.html">options_page</a>": "<em>aFile</em>.html",
"<a href="#permissions">permissions</a>": [...],
"<a href="npapi.html">plugins</a>": [...],
"<a href="autoupdate.html">update_url</a>": "http://<em>path/to/updateInfo</em>.xml"
- "<a href="#incognito">incognito</a>": "<em>split</em> or <em>spanning</em>",
}
</pre>
@@ -370,6 +377,19 @@ with links to where they're described in detail,
see the <a href="#overview">Field summary</a>.
</p>
+<h3 id="default_locale">default_locale</h3>
+
+<p>
+Specifies the subdirectory of <code>_locales</code>
+that contains the default strings for this extension.
+This field is <b>required</b> in extensions
+that have a <code>_locales</code> directory;
+it <b>must be absent</b> in extensions
+that have no <code>_locales</code> directory.
+For details, see
+<a href="i18n.html">Internationalization</a>.
+</p>
+
<h3 id="description">description</h3>
<p>
@@ -384,6 +404,15 @@ You can specify locale-specific strings for this field;
see <a href="i18n.html">Internationalization</a> for details.
</p>
+<h3 id="homepage_url">homepage_url</h3>
+
+<p>
+The URL of the homepage for this extension. The extensions management page (chrome://extensions)
+will contain a link to this URL. This field is particularly useful if you
+<a href="hosting.html">host the extension on your own site</a>. If you distribute your
+extension using the <a href="http://chrome.google.com/extensions">gallery</a>,
+the homepage URL defaults to the extension's own gallery page.
+</p>
<h3 id="icons">icons</h3>
@@ -428,8 +457,6 @@ extension developers are using the documented sizes. If you use other sizes,
your icon may look bad in future versions of the browser.
</p>
-
-
<p>
If you submit your extension to the
<a href="https://chrome.google.com/extensions">gallery</a>,
@@ -441,17 +468,35 @@ see the
<a href="http://www.google.com/support/chrome/bin/answer.py?answer=113909">gallery help</a>.
</p>
-<h3 id="default_locale">default_locale</h3>
+<h3 id="incognito">incognito</h3>
<p>
-Specifies the subdirectory of <code>_locales</code>
-that contains the default strings for this extension.
-This field is <b>required</b> in extensions
-that have a <code>_locales</code> directory;
-it <b>must be absent</b> in extensions
-that have no <code>_locales</code> directory.
-For details, see
-<a href="i18n.html">Internationalization</a>.
+Either "spanning" or "split", to specify how this extension will
+behave if allowed to run in incognito mode.
+</p>
+
+<p>
+The default for extensions is "spanning", which means that the extension
+will run in a single shared process. Any events or messages from an incognito
+tab will be sent to the shared process, with an <em>incognito</em> flag
+indicating where it came from.
+</p>
+
+<p>
+The default for installable web apps is "split",
+which means that all app pages in
+an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process.
+This incognito process runs along side the regular process, but has a separate
+memory-only cookie store. Each process sees events and messages only from its
+own context (for example, the incognito process will see only incognito tab updates).
+The processes are unable to communicate with each other.
+</p>
+
+<p>
+As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use
+<em>split</em> incognito behavior. If your extension or app needs to be logged
+into a remote server or persist settings locally, use <em>spanning</em>
+incognito behavior.
</p>
<h3 id="key">key</h3>
@@ -607,6 +652,11 @@ The following table lists the permissions an extension can use.
<a href="idle.html">chrome.idle</a> module. </td>
</tr>
<tr>
+ <td> "management" </td>
+ <td> Required if the extension uses the
+ <a href="management.html">chrome.management</a> module. </td>
+</tr>
+<tr>
<td> "notifications" </td>
<td> Allows the extension to use the proposed HTML5
<a href="http://www.chromium.org/developers/design-documents/desktop-notifications/api-specification">notification API</a>
@@ -626,7 +676,16 @@ The following table lists the permissions an extension can use.
<td> Provides an unlimited quota for storing HTML5 client-side data,
such as databases and local storage files.
Without this permission, the extension is limited to
- 5 MB of local storage. </td>
+ 5 MB of local storage.
+
+ <p class="note">
+ <b>Note:</b>
+ This permission applies only to Web SQL Database and application cache
+ (see issue <a href="http://crbug.com/58985">58985</a>).
+ Also, it doesn't currently work with wildcard subdomains such as
+ <code>http://*.example.com</code>.
+ </p>
+ </td>
</tr>
</tbody></table>
@@ -680,36 +739,6 @@ For more information, see
<a href="autoupdate.html">Autoupdating</a>.
</p>
-<h3 id="incognito">incognito</h3>
-
-<p>
-Either <em>split</em> or <em>spanning</em>, to specify how this extension will
-behave if allowed to run in incognito.
-</p>
-
-<p>
-<em>spanning</em> is the default for extensions, and means that the extension
-will run in a single shared process. Any events or messages from an incognito
-tab will be sent to the shared process, with an <em>incognito</em> flag
-indicating where it came from.
-</p>
-
-<p>
-<em>split</em> is the default for apps, and it means that all app pages in
-an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process.
-This incognito process runs along side the regular process, but has a separate
-memory-only cookie store. Each process sees events and messages only from its
-own context (e.g. the incognito process will only see incognito tab updates).
-The processes are unable to communicate with each other.
-</p>
-
-<p>
-As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use
-<em>split</em> incognito behavior. If your extension or app needs to be logged
-into a remote server or persist settings locally, use <em>spanning</em>
-incognito behavior.
-</p>
-
<!-- [PENDING: Possibly: point to the gallery and make a big deal of the fact that autoupdating is free if you use the gallery.] -->
</div>
diff --git a/chrome/common/extensions/docs/match_patterns.html b/chrome/common/extensions/docs/match_patterns.html
index 5e511b3..9a58c28 100644
--- a/chrome/common/extensions/docs/match_patterns.html
+++ b/chrome/common/extensions/docs/match_patterns.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Match Patterns - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/messaging.html b/chrome/common/extensions/docs/messaging.html
index 120a03c..343f987 100644
--- a/chrome/common/extensions/docs/messaging.html
+++ b/chrome/common/extensions/docs/messaging.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Message Passing - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/notifications.html b/chrome/common/extensions/docs/notifications.html
index fd0567a..6732897 100644
--- a/chrome/common/extensions/docs/notifications.html
+++ b/chrome/common/extensions/docs/notifications.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Desktop Notifications - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/npapi.html b/chrome/common/extensions/docs/npapi.html
index 5190257..c622beb 100644
--- a/chrome/common/extensions/docs/npapi.html
+++ b/chrome/common/extensions/docs/npapi.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>NPAPI Plugins - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/options.html b/chrome/common/extensions/docs/options.html
index 94dbfcf..9b469ff 100644
--- a/chrome/common/extensions/docs/options.html
+++ b/chrome/common/extensions/docs/options.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Options - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/override.html b/chrome/common/extensions/docs/override.html
index d1236c9..0701ea0 100644
--- a/chrome/common/extensions/docs/override.html
+++ b/chrome/common/extensions/docs/override.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Override - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -339,7 +343,7 @@ An extension can replace any one of the following pages:
<li> <b>Bookmark Manager:</b>
The page that appears when the user chooses
the Bookmark Manager menu item
- from the Tools (wrench) menu or, on Mac,
+ from the wrench menu or, on Mac,
the Bookmark Manager item from the Bookmarks menu.
You can also get to this page by entering the URL
<b>chrome://bookmarks</b>.
diff --git a/chrome/common/extensions/docs/overview.html b/chrome/common/extensions/docs/overview.html
index 2d9f9a1..714aa26 100644
--- a/chrome/common/extensions/docs/overview.html
+++ b/chrome/common/extensions/docs/overview.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Overview - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/packaging.html b/chrome/common/extensions/docs/packaging.html
index 8637ec4..6c20134 100644
--- a/chrome/common/extensions/docs/packaging.html
+++ b/chrome/common/extensions/docs/packaging.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Packaging - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/pageAction.html b/chrome/common/extensions/docs/pageAction.html
index 9bd9388..302279c 100644
--- a/chrome/common/extensions/docs/pageAction.html
+++ b/chrome/common/extensions/docs/pageAction.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Page Actions - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/permission_warnings.html b/chrome/common/extensions/docs/permission_warnings.html
index ce53446..4363047 100644
--- a/chrome/common/extensions/docs/permission_warnings.html
+++ b/chrome/common/extensions/docs/permission_warnings.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Permission Warnings - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,11 @@
<div>
</div>
</div>
+<<<<<<< HEAD
+ </dl>
+=======
</dl>
+>>>>>>> All communication with the cloud print proxy service from the browser now happens in the CloudPrintProxyService class. Added code to start the service process if the cloud print proxy was enabled. Also, when detect an auto-update, we send an IPC to the service process. The service process then shuts down when the browser disconnects.
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +230,12 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+<<<<<<< HEAD
+ <script>
+ initToggles();
+ </script>
+=======
+>>>>>>> All communication with the cloud print proxy service from the browser now happens in the CloudPrintProxyService class. Added code to start the service process if the cloud print proxy was enabled. Also, when detect an auto-update, we send an IPC to the service process. The service process then shuts down when the browser disconnects.
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/samples.html b/chrome/common/extensions/docs/samples.html
index 1593349..21ff76e 100644
--- a/chrome/common/extensions/docs/samples.html
+++ b/chrome/common/extensions/docs/samples.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Samples - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -290,7 +294,7 @@
<!-- STATIC CONTENT PLACEHOLDER -->
<div id="static"><link rel="stylesheet" href="css/samples.css">
-<script>var search_data = {"0262260daf0c8f7b28feff2ef23b05e7abf9d1e0":"A BROWSER ACTION WHICH CHANGES ITS ICON WHEN CLICKED. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON","ea2894c41cb8e80a4433a3e6c5772dadce9be90d":"A BROWSER ACTION WITH A POPUP THAT CHANGES THE PAGE COLOR. BROWSER_ACTION POPUP TABS CHROME.TABS.EXECUTESCRIPT","ede3c47b7757245be42ec33fd5ca63df4b490066":"A BROWSER ACTION WITH NO ICON THAT MAKES THE PAGE RED BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.EXECUTESCRIPT","fbf0aa1a09a15ff8cc4fc7de4fd176d6c663d07a":"ACCEPTLANGUAGE RETURNS ACCEPT LANGUAGES OF THE BROWSER BROWSER_ACTION POPUP CHROME.I18N.GETACCEPTLANGUAGES CHROME.I18N.GETMESSAGE","9a6e4ec46997fb92b324974afa08a3d007e2537f":"ANIMATED PAGE ACTION THIS EXTENSION ADDS AN ANIMATED BROWSER ACTION TO THE TOOLBAR. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.ONCLICKED CHROME.PAGEACTION.SETICON CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED","9747e3d6a3eab39bc7c17f11a80573c62d44c7e5":"BLANK NEW TAB PAGE CHROME_URL_OVERRIDES","903e7277139e1e6caec123d3319cab295d8d1b3a":"CHROME SOUNDS ENJOY A MORE MAGICAL AND IMMERSIVE EXPERIENCE WHEN BROWSING THE WEB USING THE POWER OF SOUND. BACKGROUND_PAGE BOOKMARKS OPTIONS_PAGE TABS CHROME.BOOKMARKS.ONCREATED CHROME.BOOKMARKS.ONMOVED CHROME.BOOKMARKS.ONREMOVED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.TABS.GET CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED","0e790e035a4a00b6f1def5ef9a7d7be1bce95ab5":"CHROMIUM BUILDBOT MONITOR DISPLAYS THE STATUS OF THE CHROMIUM BUILDBOT IN THE TOOLBAR. CLICK TO SEE MORE DETAILED STATUS IN A POPUP. BACKGROUND_PAGE BROWSER_ACTION NOTIFICATIONS OPTIONS_PAGE POPUP CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.GETURL","ac31228200b41a87982e386cc90d3a6eee4ad885":"CHROMIUM SEARCH ADD SUPPORT TO THE OMNIBOX TO SEARCH THE CHROMIUM SOURCE CODE. BACKGROUND_PAGE EXPERIMENTAL TABS CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTCHANGED CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTENTERED CHROME.EXPERIMENTAL.OMNIBOX.STYLEMATCH CHROME.EXPERIMENTAL.OMNIBOX.STYLENONE CHROME.EXPERIMENTAL.OMNIBOX.STYLEURL CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE","7d5d6cf195bc25480256618e360aa38c6e6fba82":"CLD DISPLAYS THE LANGUAGE OF A TAB BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.DETECTLANGUAGE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED","5d81304a17cf7ac2887484f730fbd2b01e51e166":"CONTEXT MENUS SAMPLE SHOWS SOME OF THE FEATURES OF THE CONTEXT MENUS API BACKGROUND_PAGE CONTEXTMENUS CHROME.CONTEXTMENUS.CREATE","4daa6becd0899a54776d9cf7f09613ed1a9f4d77":"COOKIE API TEST EXTENSION TESTING COOKIE API BACKGROUND_PAGE BROWSER_ACTION COOKIES TABS CHROME.BROWSERACTION.ONCLICKED CHROME.COOKIES.GET CHROME.COOKIES.GETALL CHROME.COOKIES.ONCHANGED CHROME.COOKIES.REMOVE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL","6871d09f4a96bf9d4b6cc724d00e909cee0f3902":"CROSS-DOMAIN XMLHTTPREQUEST FROM A CONTENT SCRIPT DEMONSTRATES A METHOD TO MAKE A CROSS-DOMAIN XMLHTTPREQUEST FETCH FROM A CONTENT SCRIPT. THIS EXTENSION FETCHES THE CURRENT TRENDING TOPICS FROM TWITTER AND INSERTS THEM IN AN OVERLAY AT THE TOP OF GOOGLE NEWS. VISIT HTTP://NEWS.GOOGLE.COM TO TEST THIS EXTENSION. BACKGROUND_PAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST","028eb5364924344029bcbe1d527f132fc72b34e5":"EMAIL THIS PAGE (BY GOOGLE) THIS EXTENSION ADDS AN EMAIL BUTTON TO THE TOOLBAR WHICH ALLOWS YOU TO EMAIL THE PAGE LINK USING YOUR DEFAULT MAIL CLIENT OR GMAIL. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.CONNECT CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.UPDATE","763a08e9b06595d785568a8d392b95a2f3700258":"EVENT TRACKING WITH GOOGLE ANALYTICS A SAMPLE EXTENSION WHICH USES GOOGLE ANALYTICS TO TRACK USAGE. BACKGROUND_PAGE BROWSER_ACTION POPUP","4e35caa9742fb82dbd628892d23a781614f6eff6":"GOOGLE DOCUMENT LIST VIEWER DEMONSTRATES HOW TO USE OAUTH TO CONNECT THE GOOGLE DOCUMENTS LIST DATA API. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","bb57f7a0132cbeb36ad7e7bb0ab75c21704234ca":"GOOGLE MAIL CHECKER DISPLAYS THE NUMBER OF UNREAD MESSAGES IN YOUR GOOGLE MAIL INBOX. YOU CAN ALSO CLICK THE BUTTON TO OPEN YOUR INBOX. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.ONUPDATED CHROME.TABS.UPDATE","1682e05ea9a1bde985123b04f6f8ac50a8a64033":"GOOGLE WAVE NOTIFIER FIND OUT WHEN YOU HAVE NEW WAVES AND PREVIEW THEM FAST. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","14b9651fda4e57b2a5914ba73a779812201b750a":"HELLO WORLD THE FIRST EXTENSION THAT I MADE. BROWSER_ACTION POPUP","2020d72f2577f53caf8e94e3dbac0fb849ceaa4d":"IDLE - SIMPLE EXAMPLE DEMONSTRATES THE IDLE API BACKGROUND_PAGE BROWSER_ACTION IDLE CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.IDLE.ONSTATECHANGED CHROME.IDLE.QUERYSTATE","0ea1588bd07b20338fc21f725de1542a5fdf9726":"IGOOGLE NEW TAB PAGE CHROME_URL_OVERRIDES","646325c25f572a1d15edc73d057f821d847a4fbe":"IMAGEINFO GET IMAGE INFO FOR IMAGES, INCLUDING EXIF DATA BACKGROUND_PAGE CONTEXTMENUS TABS CHROME.CONTEXTMENUS.CREATE CHROME.TABS.GET CHROME.TABS.GETCURRENT CHROME.WINDOWS.CREATE CHROME.WINDOWS.UPDATE","ec97ec20ca2f095d081e39f1565fc12af09ef067":"MAPPY FINDS ADDRESSES IN THE WEB PAGE YOURE ON AND POPS UP A MAP WINDOW. BACKGROUND_PAGE PAGE_ACTION POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.SENDREQUEST","b2f5f8a790e16f091a7e4e0a39b2d0a6d32e3a6d":"MERGE WINDOWS MERGES ALL OF THE BROWSERS WINDOWS INTO THE CURRENT WINDOW BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.MOVE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT","51a83d2ba3a32e3ff1bdb624d4e18ccec4c4038e":"MESSAGE TIMER TIMES HOW LONG IT TAKES TO SEND A MESSAGE TO A CONTENT SCRIPT AND BACK. BROWSER_ACTION POPUP TABS CHROME.EXTENSION.ONCONNECT CHROME.EXTENSION.ONREQUEST CHROME.TABS.CONNECT CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.SENDREQUEST","4f6785ec4f937add6728615682dd37c9a42d9548":"MY BOOKMARKS A BROWSER ACTION WITH A POPUP DUMP OF ALL BOOKMARKS, INCLUDING SEARCH, ADD, EDIT AND DELETE. BOOKMARKS BROWSER_ACTION POPUP TABS CHROME.BOOKMARKS.CREATE CHROME.BOOKMARKS.GET CHROME.BOOKMARKS.GETTREE CHROME.BOOKMARKS.REMOVE CHROME.BOOKMARKS.UPDATE CHROME.TABS.CREATE","3aea027164cb9b732ba4a8c51cb93708891726ef":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.TABS.CREATE","597015d3bcce3da693b02314afd607bec4f55291":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.TABS.CREATE","6444e5c8ae112a6a433909c5e770669cd16e2e5f":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE","f799e26ceef2367cf836f24bcb47df4398b0df58":"NOTIFICATION DEMO SHOWS OFF DESKTOP NOTIFICATIONS, WHICH ARE TOAST WINDOWS THAT POP UP ON THE DESKTOP. BACKGROUND_PAGE NOTIFICATIONS OPTIONS_PAGE TABS CHROME.TABS.CREATE","a88ab12b0241ee3dac6e74bb04da7964fab0f57d":"OMNIBOX EXAMPLE BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTCHANGED CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTENTERED","8d0a50b57c26bb498be592e871001ffed91541b4":"PAGE ACTION BY CONTENT SHOWS A PAGE ACTION FOR HTML PAGES CONTAINING THE WORD SANDWICH BACKGROUND_PAGE PAGE_ACTION CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.PAGEACTION.SHOW","80b86ccc6e8520660fa591caa565826f0ed1b12c":"PAGE ACTION BY URL SHOWS A PAGE ACTION FOR URLS WHICH HAVE THE LETTER G IN THEM. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.SHOW CHROME.TABS.ONUPDATED","d74c3c18a1c1dd18b035149105a306f837c8823e":"PAGE BENCHMARKER CHROMIUM PAGE BENCHMARKER. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.CONNECT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETEXTENSIONTABS CHROME.EXTENSION.GETURL CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETCURRENT","e6ae17ab4ccfd7e059c8c01f25760ca5d894c7fd":"PRINT THIS PAGE ADDS A PRINT BUTTON TO THE BROWSER. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.UPDATE","beff6ecd9677dea0a7c648c5042165b48bb66f09":"PROCESS MONITOR ADDS A BROWSER ACTION THAT MONITORS RESOURCE USAGE OF ALL BROWSER PROCESSES. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.ONUPDATED","56a8d2ac24ca7bba78fd88ad57f43fc13c784497":"SAMPLE - OAUTH CONTACTS USES OAUTH TO CONNECT TO GOOGLES CONTACTS SERVICE AND DISPLAY A LIST OF YOUR CONTACTS. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","38f6e1e17756ede38b1364c7114a738ca717dcbb":"SANDWICHBAR SHOWS AN INFOBAR ON PAGES WHICH CONTAIN THE WORD SANDWICH BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.INFOBARS.SHOW CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST","fc89b35755483af30b66cd72cefa34a43a3e8312":"SHOW TABS IN PROCESS ADDS A BROWSER ACTION SHOWING WHICH TABS SHARE THE CURRENT TABS PROCESS. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.GETPROCESSIDFORTAB CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.UPDATE","230463f2d5c3d4d0ca13c230e1f00f2aae0a8a64":"TAB INSPECTOR UTILITY FOR WORKING WITH THE EXTENSION TABS API BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.MOVE CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.CREATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.GETLASTFOCUSED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED CHROME.WINDOWS.REMOVE CHROME.WINDOWS.UPDATE","e1697cacebad05218798bf3e8a0f724517f0e8c3":"TEST SCREENSHOT EXTENSION DEMONSTRATE SCREENSHOT FUNCTIONALITY IN THE CHROME.TABS API. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.EXTENSION.GETVIEWS CHROME.TABS.CAPTUREVISIBLETAB CHROME.TABS.CREATE CHROME.TABS.ONUPDATED","b3de91ab04b7d7a2670ca7ee9d740eb42cead0b6":"TYPED URL HISTORY READS YOUR HISTORY, AND SHOWS THE TOP TEN PAGES YOU GO TO BY TYPING THE URL. BROWSER_ACTION HISTORY TABS CHROME.HISTORY.GETVISITS CHROME.HISTORY.SEARCH CHROME.TABS.CREATE"}</script>
+<script>var search_data = {"0262260daf0c8f7b28feff2ef23b05e7abf9d1e0":"A BROWSER ACTION WHICH CHANGES ITS ICON WHEN CLICKED. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON","ea2894c41cb8e80a4433a3e6c5772dadce9be90d":"A BROWSER ACTION WITH A POPUP THAT CHANGES THE PAGE COLOR. BROWSER_ACTION POPUP TABS CHROME.TABS.EXECUTESCRIPT","ede3c47b7757245be42ec33fd5ca63df4b490066":"A BROWSER ACTION WITH NO ICON THAT MAKES THE PAGE RED BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.EXECUTESCRIPT","fbf0aa1a09a15ff8cc4fc7de4fd176d6c663d07a":"ACCEPTLANGUAGE RETURNS ACCEPT LANGUAGES OF THE BROWSER BROWSER_ACTION POPUP CHROME.I18N.GETACCEPTLANGUAGES CHROME.I18N.GETMESSAGE","9a6e4ec46997fb92b324974afa08a3d007e2537f":"ANIMATED PAGE ACTION THIS EXTENSION ADDS AN ANIMATED BROWSER ACTION TO THE TOOLBAR. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.ONCLICKED CHROME.PAGEACTION.SETICON CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED","9747e3d6a3eab39bc7c17f11a80573c62d44c7e5":"BLANK NEW TAB PAGE CHROME_URL_OVERRIDES","903e7277139e1e6caec123d3319cab295d8d1b3a":"CHROME SOUNDS ENJOY A MORE MAGICAL AND IMMERSIVE EXPERIENCE WHEN BROWSING THE WEB USING THE POWER OF SOUND. BACKGROUND_PAGE BOOKMARKS OPTIONS_PAGE TABS CHROME.BOOKMARKS.ONCREATED CHROME.BOOKMARKS.ONMOVED CHROME.BOOKMARKS.ONREMOVED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.TABS.GET CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED","0e790e035a4a00b6f1def5ef9a7d7be1bce95ab5":"CHROMIUM BUILDBOT MONITOR DISPLAYS THE STATUS OF THE CHROMIUM BUILDBOT IN THE TOOLBAR. CLICK TO SEE MORE DETAILED STATUS IN A POPUP. BACKGROUND_PAGE BROWSER_ACTION NOTIFICATIONS OPTIONS_PAGE POPUP CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.GETURL","ac31228200b41a87982e386cc90d3a6eee4ad885":"CHROMIUM SEARCH ADD SUPPORT TO THE OMNIBOX TO SEARCH THE CHROMIUM SOURCE CODE. BACKGROUND_PAGE EXPERIMENTAL TABS CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTCHANGED CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTENTERED CHROME.EXPERIMENTAL.OMNIBOX.STYLEMATCH CHROME.EXPERIMENTAL.OMNIBOX.STYLENONE CHROME.EXPERIMENTAL.OMNIBOX.STYLEURL CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE","7d5d6cf195bc25480256618e360aa38c6e6fba82":"CLD DISPLAYS THE LANGUAGE OF A TAB BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.TABS.DETECTLANGUAGE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED","5d81304a17cf7ac2887484f730fbd2b01e51e166":"CONTEXT MENUS SAMPLE SHOWS SOME OF THE FEATURES OF THE CONTEXT MENUS API BACKGROUND_PAGE CONTEXTMENUS CHROME.CONTEXTMENUS.CREATE","4daa6becd0899a54776d9cf7f09613ed1a9f4d77":"COOKIE API TEST EXTENSION TESTING COOKIE API BACKGROUND_PAGE BROWSER_ACTION COOKIES TABS CHROME.BROWSERACTION.ONCLICKED CHROME.COOKIES.GET CHROME.COOKIES.GETALL CHROME.COOKIES.ONCHANGED CHROME.COOKIES.REMOVE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL","6871d09f4a96bf9d4b6cc724d00e909cee0f3902":"CROSS-DOMAIN XMLHTTPREQUEST FROM A CONTENT SCRIPT DEMONSTRATES A METHOD TO MAKE A CROSS-DOMAIN XMLHTTPREQUEST FETCH FROM A CONTENT SCRIPT. THIS EXTENSION FETCHES THE CURRENT TRENDING TOPICS FROM TWITTER AND INSERTS THEM IN AN OVERLAY AT THE TOP OF GOOGLE NEWS. VISIT HTTP://NEWS.GOOGLE.COM TO TEST THIS EXTENSION. BACKGROUND_PAGE CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST","028eb5364924344029bcbe1d527f132fc72b34e5":"EMAIL THIS PAGE (BY GOOGLE) THIS EXTENSION ADDS AN EMAIL BUTTON TO THE TOOLBAR WHICH ALLOWS YOU TO EMAIL THE PAGE LINK USING YOUR DEFAULT MAIL CLIENT OR GMAIL. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.CONNECT CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.UPDATE","763a08e9b06595d785568a8d392b95a2f3700258":"EVENT TRACKING WITH GOOGLE ANALYTICS A SAMPLE EXTENSION WHICH USES GOOGLE ANALYTICS TO TRACK USAGE. BACKGROUND_PAGE BROWSER_ACTION POPUP","e3df888a89e35bdeb9c8bc8d03be5e1851b97c68":"EXTENSION DOCS SEARCH SEARCH THE CHROME EXTENSIONS DOCUMENTATION. TO USE, TYPE CRDOC PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE EXPERIMENTAL TABS CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTCHANGED CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTENTERED CHROME.EXPERIMENTAL.OMNIBOX.STYLEMATCH CHROME.EXPERIMENTAL.OMNIBOX.STYLENONE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.ONREMOVED CHROME.TABS.UPDATE","4e35caa9742fb82dbd628892d23a781614f6eff6":"GOOGLE DOCUMENT LIST VIEWER DEMONSTRATES HOW TO USE OAUTH TO CONNECT THE GOOGLE DOCUMENTS LIST DATA API. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.BROWSERACTION.SETBADGETEXT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","bb57f7a0132cbeb36ad7e7bb0ab75c21704234ca":"GOOGLE MAIL CHECKER DISPLAYS THE NUMBER OF UNREAD MESSAGES IN YOUR GOOGLE MAIL INBOX. YOU CAN ALSO CLICK THE BUTTON TO OPEN YOUR INBOX. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.ONUPDATED CHROME.TABS.UPDATE","1682e05ea9a1bde985123b04f6f8ac50a8a64033":"GOOGLE WAVE NOTIFIER FIND OUT WHEN YOU HAVE NEW WAVES AND PREVIEW THEM FAST. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","14b9651fda4e57b2a5914ba73a779812201b750a":"HELLO WORLD THE FIRST EXTENSION THAT I MADE. BROWSER_ACTION POPUP","2020d72f2577f53caf8e94e3dbac0fb849ceaa4d":"IDLE - SIMPLE EXAMPLE DEMONSTRATES THE IDLE API BACKGROUND_PAGE BROWSER_ACTION IDLE CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.IDLE.ONSTATECHANGED CHROME.IDLE.QUERYSTATE","0ea1588bd07b20338fc21f725de1542a5fdf9726":"IGOOGLE NEW TAB PAGE CHROME_URL_OVERRIDES","646325c25f572a1d15edc73d057f821d847a4fbe":"IMAGEINFO GET IMAGE INFO FOR IMAGES, INCLUDING EXIF DATA BACKGROUND_PAGE CONTEXTMENUS TABS CHROME.CONTEXTMENUS.CREATE CHROME.TABS.GET CHROME.TABS.GETCURRENT CHROME.WINDOWS.CREATE CHROME.WINDOWS.UPDATE","ec97ec20ca2f095d081e39f1565fc12af09ef067":"MAPPY FINDS ADDRESSES IN THE WEB PAGE YOURE ON AND POPS UP A MAP WINDOW. BACKGROUND_PAGE PAGE_ACTION POPUP TABS CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.ONREQUEST CHROME.PAGEACTION.HIDE CHROME.PAGEACTION.SETTITLE CHROME.PAGEACTION.SHOW CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.SENDREQUEST","b2f5f8a790e16f091a7e4e0a39b2d0a6d32e3a6d":"MERGE WINDOWS MERGES ALL OF THE BROWSERS WINDOWS INTO THE CURRENT WINDOW BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.MOVE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT","51a83d2ba3a32e3ff1bdb624d4e18ccec4c4038e":"MESSAGE TIMER TIMES HOW LONG IT TAKES TO SEND A MESSAGE TO A CONTENT SCRIPT AND BACK. BROWSER_ACTION POPUP TABS CHROME.EXTENSION.ONCONNECT CHROME.EXTENSION.ONREQUEST CHROME.TABS.CONNECT CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.SENDREQUEST","4f6785ec4f937add6728615682dd37c9a42d9548":"MY BOOKMARKS A BROWSER ACTION WITH A POPUP DUMP OF ALL BOOKMARKS, INCLUDING SEARCH, ADD, EDIT AND DELETE. BOOKMARKS BROWSER_ACTION POPUP TABS CHROME.BOOKMARKS.CREATE CHROME.BOOKMARKS.GET CHROME.BOOKMARKS.GETTREE CHROME.BOOKMARKS.REMOVE CHROME.BOOKMARKS.UPDATE CHROME.TABS.CREATE","3aea027164cb9b732ba4a8c51cb93708891726ef":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.TABS.CREATE","597015d3bcce3da693b02314afd607bec4f55291":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.TABS.CREATE","6444e5c8ae112a6a433909c5e770669cd16e2e5f":"NEWS READER DISPLAYS THE FIRST 5 ITEMS FROM THE GOOGLE NEWS - TOP NEWS RSS FEED IN A POPUP. BROWSER_ACTION POPUP TABS CHROME.I18N.GETMESSAGE CHROME.TABS.CREATE","f799e26ceef2367cf836f24bcb47df4398b0df58":"NOTIFICATION DEMO SHOWS OFF DESKTOP NOTIFICATIONS, WHICH ARE TOAST WINDOWS THAT POP UP ON THE DESKTOP. BACKGROUND_PAGE NOTIFICATIONS OPTIONS_PAGE TABS CHROME.TABS.CREATE","e787b322bddbc6289bb31b7d7550b1bf6456a80b":"OMNIBOX EXAMPLE TO USE, TYPE OMNIX PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTCHANGED CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTENTERED","8d0a50b57c26bb498be592e871001ffed91541b4":"PAGE ACTION BY CONTENT SHOWS A PAGE ACTION FOR HTML PAGES CONTAINING THE WORD SANDWICH BACKGROUND_PAGE PAGE_ACTION CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST CHROME.PAGEACTION.SHOW","80b86ccc6e8520660fa591caa565826f0ed1b12c":"PAGE ACTION BY URL SHOWS A PAGE ACTION FOR URLS WHICH HAVE THE LETTER G IN THEM. BACKGROUND_PAGE PAGE_ACTION TABS CHROME.PAGEACTION.SHOW CHROME.TABS.ONUPDATED","d74c3c18a1c1dd18b035149105a306f837c8823e":"PAGE BENCHMARKER CHROMIUM PAGE BENCHMARKER. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.CONNECT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETEXTENSIONTABS CHROME.EXTENSION.GETURL CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETCURRENT","e6ae17ab4ccfd7e059c8c01f25760ca5d894c7fd":"PRINT THIS PAGE ADDS A PRINT BUTTON TO THE BROWSER. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.TABS.UPDATE","beff6ecd9677dea0a7c648c5042165b48bb66f09":"PROCESS MONITOR ADDS A BROWSER ACTION THAT MONITORS RESOURCE USAGE OF ALL BROWSER PROCESSES. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.ONUPDATED","56a8d2ac24ca7bba78fd88ad57f43fc13c784497":"SAMPLE - OAUTH CONTACTS USES OAUTH TO CONNECT TO GOOGLES CONTACTS SERVICE AND DISPLAY A LIST OF YOUR CONTACTS. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETICON CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE","38f6e1e17756ede38b1364c7114a738ca717dcbb":"SANDWICHBAR SHOWS AN INFOBAR ON PAGES WHICH CONTAIN THE WORD SANDWICH BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.INFOBARS.SHOW CHROME.EXTENSION.ONREQUEST CHROME.EXTENSION.SENDREQUEST","fc89b35755483af30b66cd72cefa34a43a3e8312":"SHOW TABS IN PROCESS ADDS A BROWSER ACTION SHOWING WHICH TABS SHARE THE CURRENT TABS PROCESS. BROWSER_ACTION EXPERIMENTAL POPUP TABS CHROME.EXPERIMENTAL.PROCESSES.GETPROCESSIDFORTAB CHROME.TABS.GET CHROME.TABS.GETSELECTED CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.UPDATE","230463f2d5c3d4d0ca13c230e1f00f2aae0a8a64":"TAB INSPECTOR UTILITY FOR WORKING WITH THE EXTENSION TABS API BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.MOVE CHROME.TABS.ONATTACHED CHROME.TABS.ONCREATED CHROME.TABS.ONDETACHED CHROME.TABS.ONMOVED CHROME.TABS.ONREMOVED CHROME.TABS.ONSELECTIONCHANGED CHROME.TABS.ONUPDATED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.CREATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETALL CHROME.WINDOWS.GETCURRENT CHROME.WINDOWS.GETLASTFOCUSED CHROME.WINDOWS.ONCREATED CHROME.WINDOWS.ONFOCUSCHANGED CHROME.WINDOWS.ONREMOVED CHROME.WINDOWS.REMOVE CHROME.WINDOWS.UPDATE","e1697cacebad05218798bf3e8a0f724517f0e8c3":"TEST SCREENSHOT EXTENSION DEMONSTRATE SCREENSHOT FUNCTIONALITY IN THE CHROME.TABS API. BACKGROUND_PAGE BROWSER_ACTION TABS CHROME.BROWSERACTION.ONCLICKED CHROME.EXTENSION.GETURL CHROME.EXTENSION.GETVIEWS CHROME.TABS.CAPTUREVISIBLETAB CHROME.TABS.CREATE CHROME.TABS.ONUPDATED","b3de91ab04b7d7a2670ca7ee9d740eb42cead0b6":"TYPED URL HISTORY READS YOUR HISTORY, AND SHOWS THE TOP TEN PAGES YOU GO TO BY TYPING THE URL. BROWSER_ACTION HISTORY TABS CHROME.HISTORY.GETVISITS CHROME.HISTORY.SEARCH CHROME.TABS.CREATE"}</script>
<script src="js/sample_search.js"></script>
@@ -1019,6 +1023,56 @@
</ul>
</div>
<div><a href="examples/tutorials/analytics.zip">Download .zip</a></div>
+</div><div class="sample" id="e3df888a89e35bdeb9c8bc8d03be5e1851b97c68">
+ <img class="icon" src="examples/api/omnibox/extension-docs/icon-128.png">
+ <img class="icon" src="images/sample-default-icon.png" style="display: none; ">
+ <h2 class="name">
+ <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/">Extension Docs Search</a>
+ </h2>
+ <p class="metadata features">Uses
+ <span>
+ <strong>background_page</strong><span>, </span>
+ <span style="display: none; "> and</span>
+ </span><span>
+ <strong>experimental</strong><span style="display: none; ">, </span>
+ <span> and</span>
+ </span><span>
+ <strong>tabs</strong><span style="display: none; ">, </span>
+ <span style="display: none; "> and</span>
+ </span>
+ </p>
+ <p>Search the Chrome Extensions documentation. To use, type 'crdoc' plus a search term into the Omnibox.</p>
+ <div class="apicalls"><strong>Calls:</strong>
+ <ul>
+ <li>
+ <code><a href="experimental.omnibox.html#event-onInputChanged">chrome.experimental.omnibox.onInputChanged</a></code>
+ </li><li>
+ <code><a href="experimental.omnibox.html#event-onInputEntered">chrome.experimental.omnibox.onInputEntered</a></code>
+ </li><li>
+ <code><a href="experimental.omnibox.html#method-styleMatch">chrome.experimental.omnibox.styleMatch</a></code>
+ </li><li>
+ <code><a href="experimental.omnibox.html#method-styleNone">chrome.experimental.omnibox.styleNone</a></code>
+ </li><li>
+ <code><a href="tabs.html#method-create">chrome.tabs.create</a></code>
+ </li><li>
+ <code><a href="tabs.html#method-get">chrome.tabs.get</a></code>
+ </li><li>
+ <code><a href="tabs.html#event-onRemoved">chrome.tabs.onRemoved</a></code>
+ </li><li>
+ <code><a href="tabs.html#method-update">chrome.tabs.update</a></code>
+ </li>
+ </ul>
+ </div>
+ <div class="sourcefiles"><strong>Source files:</strong>
+ <ul>
+ <li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/background.html?content-type=text/plain">background.html</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/extension-docs/manifest.json?content-type=text/plain">manifest.json</a></code>
+ </li>
+ </ul>
+ </div>
+ <div><a href="examples/api/omnibox/extension-docs.zip">Download .zip</a></div>
</div><div class="sample" id="4e35caa9742fb82dbd628892d23a781614f6eff6">
<img class="icon" src="examples/extensions/gdocs/img/docs_spreadsheets-128.gif">
<img class="icon" src="images/sample-default-icon.png" style="display: none; ">
@@ -1822,11 +1876,11 @@
</ul>
</div>
<div><a href="examples/api/notifications.zip">Download .zip</a></div>
-</div><div class="sample" id="a88ab12b0241ee3dac6e74bb04da7964fab0f57d">
+</div><div class="sample" id="e787b322bddbc6289bb31b7d7550b1bf6456a80b">
<img class="icon" style="display: none; ">
<img class="icon" src="images/sample-default-icon.png">
<h2 class="name">
- <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/">Omnibox Example</a>
+ <a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/simple-example/">Omnibox Example</a>
</h2>
<p class="metadata features">Uses
<span>
@@ -1837,7 +1891,7 @@
<span style="display: none; "> and</span>
</span>
</p>
- <p></p>
+ <p>To use, type 'omnix' plus a search term into the Omnibox.</p>
<div class="apicalls"><strong>Calls:</strong>
<ul>
<li>
@@ -1850,13 +1904,13 @@
<div class="sourcefiles"><strong>Source files:</strong>
<ul>
<li>
- <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/background.html?content-type=text/plain">background.html</a></code>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/simple-example/background.html?content-type=text/plain">background.html</a></code>
</li><li>
- <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/manifest.json?content-type=text/plain">manifest.json</a></code>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/omnibox/simple-example/manifest.json?content-type=text/plain">manifest.json</a></code>
</li>
</ul>
</div>
- <div><a href="examples/api/omnibox.zip">Download .zip</a></div>
+ <div><a href="examples/api/omnibox/simple-example.zip">Download .zip</a></div>
</div><div class="sample" id="8d0a50b57c26bb498be592e871001ffed91541b4">
<img class="icon" src="examples/api/pageAction/pageaction_by_content/sandwich-128.png">
<img class="icon" src="images/sample-default-icon.png" style="display: none; ">
@@ -2002,6 +2056,22 @@
<li>
<code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/background.html?content-type=text/plain">background.html</a></code>
</li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-1.4.2.min.js?content-type=text/plain">jquery/jquery-1.4.2.min.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery-ui-1.8.4.custom.min.js?content-type=text/plain">jquery/jquery-ui-1.8.4.custom.min.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.client.js?content-type=text/plain">jquery/jquery.client.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.dashes.js?content-type=text/plain">jquery/jquery.flot.dashes.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.js?content-type=text/plain">jquery/jquery.flot.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.min.js?content-type=text/plain">jquery/jquery.flot.min.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.navigate.js?content-type=text/plain">jquery/jquery.flot.navigate.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jquery/jquery.flot.valuelabels.js?content-type=text/plain">jquery/jquery.flot.valuelabels.js</a></code>
+ </li><li>
<code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jst/jsevalcontext.js?content-type=text/plain">jst/jsevalcontext.js</a></code>
</li><li>
<code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/jst/jstemplate.js?content-type=text/plain">jst/jstemplate.js</a></code>
@@ -2015,6 +2085,10 @@
<code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/options.html?content-type=text/plain">options.html</a></code>
</li><li>
<code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/script.js?content-type=text/plain">script.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/util/sorttable.js?content-type=text/plain">util/sorttable.js</a></code>
+ </li><li>
+ <code><a target="_blank" href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/benchmark/util/table2CSV.js?content-type=text/plain">util/table2CSV.js</a></code>
</li>
</ul>
</div>
diff --git a/chrome/common/extensions/docs/samples.json b/chrome/common/extensions/docs/samples.json
index 30a3b02..bc67080 100644
--- a/chrome/common/extensions/docs/samples.json
+++ b/chrome/common/extensions/docs/samples.json
@@ -51,6 +51,7 @@
"chrome.experimental.clipboard.executeCopy": "experimental.clipboard.html#method-executeCopy",
"chrome.bookmarks.move": "bookmarks.html#method-move",
"chrome.experimental.webRequest.onBeforeRedirect": "experimental.webRequest.html#event-onBeforeRedirect",
+ "chrome.management.get": "management.html#method-get",
"chrome.tabs.getCurrent": "tabs.html#method-getCurrent",
"chrome.experimental.sidebar.getState": "experimental.sidebar.html#method-getState",
"chrome.management.launchApp": "management.html#method-launchApp",
@@ -567,6 +568,37 @@
{
"features": [
"background_page",
+ "experimental",
+ "tabs"
+ ],
+ "icon": "icon-128.png",
+ "description": "Search the Chrome Extensions documentation. To use, type 'crdoc' plus a search term into the Omnibox.",
+ "search_string": "EXTENSION DOCS SEARCH SEARCH THE CHROME EXTENSIONS DOCUMENTATION. TO USE, TYPE CRDOC PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE EXPERIMENTAL TABS CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTCHANGED CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTENTERED CHROME.EXPERIMENTAL.OMNIBOX.STYLEMATCH CHROME.EXPERIMENTAL.OMNIBOX.STYLENONE CHROME.TABS.CREATE CHROME.TABS.GET CHROME.TABS.ONREMOVED CHROME.TABS.UPDATE",
+ "source_files": [
+ "background.html",
+ "manifest.json"
+ ],
+ "zip_path": "examples/api/omnibox/extension-docs.zip",
+ "path": "examples/api/omnibox/extension-docs/",
+ "api_calls": [
+ "chrome.experimental.omnibox.onInputChanged",
+ "chrome.experimental.omnibox.onInputEntered",
+ "chrome.experimental.omnibox.styleMatch",
+ "chrome.experimental.omnibox.styleNone",
+ "chrome.tabs.create",
+ "chrome.tabs.get",
+ "chrome.tabs.onRemoved",
+ "chrome.tabs.update"
+ ],
+ "id": "e3df888a89e35bdeb9c8bc8d03be5e1851b97c68",
+ "protocols": [
+ "http://"
+ ],
+ "name": "Extension Docs Search"
+ },
+ {
+ "features": [
+ "background_page",
"browser_action",
"options_page",
"popup",
@@ -1050,19 +1082,19 @@
"experimental"
],
"icon": null,
- "description": "",
- "search_string": "OMNIBOX EXAMPLE BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTCHANGED CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTENTERED",
+ "description": "To use, type 'omnix' plus a search term into the Omnibox.",
+ "search_string": "OMNIBOX EXAMPLE TO USE, TYPE OMNIX PLUS A SEARCH TERM INTO THE OMNIBOX. BACKGROUND_PAGE EXPERIMENTAL CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTCHANGED CHROME.EXPERIMENTAL.OMNIBOX.ONINPUTENTERED",
"source_files": [
"background.html",
"manifest.json"
],
- "zip_path": "examples/api/omnibox.zip",
- "path": "examples/api/omnibox/",
+ "zip_path": "examples/api/omnibox/simple-example.zip",
+ "path": "examples/api/omnibox/simple-example/",
"api_calls": [
"chrome.experimental.omnibox.onInputChanged",
"chrome.experimental.omnibox.onInputEntered"
],
- "id": "a88ab12b0241ee3dac6e74bb04da7964fab0f57d",
+ "id": "e787b322bddbc6289bb31b7d7550b1bf6456a80b",
"protocols": [],
"name": "Omnibox Example"
},
@@ -1125,13 +1157,23 @@
"search_string": "PAGE BENCHMARKER CHROMIUM PAGE BENCHMARKER. BACKGROUND_PAGE BROWSER_ACTION OPTIONS_PAGE TABS CHROME.BROWSERACTION.ONCLICKED CHROME.BROWSERACTION.SETBADGEBACKGROUNDCOLOR CHROME.BROWSERACTION.SETBADGETEXT CHROME.BROWSERACTION.SETTITLE CHROME.EXTENSION.CONNECT CHROME.EXTENSION.GETBACKGROUNDPAGE CHROME.EXTENSION.GETEXTENSIONTABS CHROME.EXTENSION.GETURL CHROME.EXTENSION.ONCONNECT CHROME.TABS.CREATE CHROME.TABS.EXECUTESCRIPT CHROME.TABS.GET CHROME.TABS.GETALLINWINDOW CHROME.TABS.GETSELECTED CHROME.TABS.REMOVE CHROME.TABS.UPDATE CHROME.WINDOWS.GET CHROME.WINDOWS.GETCURRENT",
"source_files": [
"background.html",
+ "jquery/jquery-1.4.2.min.js",
+ "jquery/jquery-ui-1.8.4.custom.min.js",
+ "jquery/jquery.client.js",
+ "jquery/jquery.flot.dashes.js",
+ "jquery/jquery.flot.js",
+ "jquery/jquery.flot.min.js",
+ "jquery/jquery.flot.navigate.js",
+ "jquery/jquery.flot.valuelabels.js",
"jst/jsevalcontext.js",
"jst/jstemplate.js",
"jst/jstemplate_test.js",
"jst/util.js",
"manifest.json",
"options.html",
- "script.js"
+ "script.js",
+ "util/sorttable.js",
+ "util/table2CSV.js"
],
"zip_path": "examples/extensions/benchmark.zip",
"path": "examples/extensions/benchmark/",
@@ -1409,4 +1451,4 @@
"name": "Typed URL History"
}
]
-} \ No newline at end of file
+}
diff --git a/chrome/common/extensions/docs/static/api_other.html b/chrome/common/extensions/docs/static/api_other.html
index 95bf464..e9ba86f 100644
--- a/chrome/common/extensions/docs/static/api_other.html
+++ b/chrome/common/extensions/docs/static/api_other.html
@@ -36,7 +36,7 @@ E.g. window.open(someUrl). --></dd>
<ul>
<li> audio
(<a href="http://www.html5rocks.com/tutorials/audio/quick/">tutorial</a>) </li>
- <li> app cache
+ <li> application cache
(<a href="http://www.html5rocks.com/tutorials/appcache/beginner/">tutorial</a>) </li>
<li> canvas </li>
<li> geolocation
diff --git a/chrome/common/extensions/docs/static/browserAction.html b/chrome/common/extensions/docs/static/browserAction.html
index 224c247..2a35b5d 100644
--- a/chrome/common/extensions/docs/static/browserAction.html
+++ b/chrome/common/extensions/docs/static/browserAction.html
@@ -148,7 +148,7 @@ in the <a href="#manifest">manifest</a>, or call the
Browser action icons should seem a little bigger
and heavier than page action icons.
<li><b>Don't</b> attempt to mimic
- Google Chrome's monochrome "wrench" and "page" icons.
+ Google Chrome's monochrome "wrench" icon.
That doesn't work well with themes, and anyway,
extensions should stand out a little.
<li><b>Do</b> use alpha transparency
diff --git a/chrome/common/extensions/docs/static/content_scripts.html b/chrome/common/extensions/docs/static/content_scripts.html
index c11a247..9cbf0c3 100644
--- a/chrome/common/extensions/docs/static/content_scripts.html
+++ b/chrome/common/extensions/docs/static/content_scripts.html
@@ -173,7 +173,7 @@ can have the following properties:</p>
</tr>
</table>
-<h3 id="include-exclude-globs">Include and exclude globs</h2>
+<h3 id="include-exclude-globs">Include and exclude globs</h3>
<p>
The content script will be injected into a page if its URL matches any <code>matches</code> pattern and any <code>include_globs</code> pattern, as long as the URL doesn't also match an <code>exclude_globs</code> pattern. Because the <code>matches</code> property is required, <code>include_globs</code> and <code>exclude_globs</code> can only be used to limit which pages will be affected.
diff --git a/chrome/common/extensions/docs/static/crx.html b/chrome/common/extensions/docs/static/crx.html
index 69f5a3d..422148b 100644
--- a/chrome/common/extensions/docs/static/crx.html
+++ b/chrome/common/extensions/docs/static/crx.html
@@ -6,7 +6,7 @@ CRX files are ZIP files with a special header and the <code>.crx</code> file
extension.
</p>
-<h2>Package header</h3>
+<h2>Package header</h2>
<p>
The header contains the author's public key and the extension's signature.
@@ -63,7 +63,7 @@ the <code>.crx</code> header in order:
</tr>
</table>
-<h2>Extension contents</h3>
+<h2>Extension contents</h2>
<p>
The extension's ZIP file is appended to the <code>*.crx</code> package after the
@@ -71,7 +71,7 @@ header. This should be the same ZIP file that the signature in the header
was generated from.
</p>
-<h2>Example</h3>
+<h2>Example</h2>
<p>
The following is an example hex dump from the beginning of a <code>.crx</code>
diff --git a/chrome/common/extensions/docs/static/faq.html b/chrome/common/extensions/docs/static/faq.html
index 0c94d9d..e9c6908 100644
--- a/chrome/common/extensions/docs/static/faq.html
+++ b/chrome/common/extensions/docs/static/faq.html
@@ -85,12 +85,22 @@ try the
<p>
As long as you are using a version of Google Chrome that supports
extensions, you already have everything you need to start writing an
- extension of your own. Select <b>Extensions</b> from the Tools menu
- <img style="vertical-align: middle; margin:0; padding:0" src="images/toolsmenu.gif" /> (or from
- the Window menu on Mac) and click <b>Developer Mode</b>. From there, you can load
- an unpacked directory of files as if it were a packaged extension, reload
- extensions, and more. For a complete tutorial, please view
- <a href="http://code.google.com/chrome/extensions/getstarted.html">this getting started guide</a>.
+ extension of your own.
+ You can start by turning on Developer mode.
+ </p>
+
+ <p>
+ Click the wrench icon
+ <img src="images/toolsmenu.gif" height="29" width="29" alt=""
+ class="nomargin" />
+ and select <b>Extensions</b> from the <b>Tools</b> menu
+ (or from the <b>Window</b> menu on Mac).
+ If there's a "+" next to "Developer mode",
+ click the "+" so it turns into a "-".
+ Now you can reload extensions,
+ load an unpacked directory of files as if it were a packaged extension,
+ and more. For a complete tutorial, see
+ <a href="http://code.google.com/chrome/extensions/getstarted.html">Getting Started</a>.
</p>
<h3 id="faq-dev-02">Can I make cross-domain Ajax requests in an extension?</h3>
@@ -388,4 +398,5 @@ win,stable,#.#.###.#,#.#.###.#</pre>
to the ticket you starred or opened. This will make it easier for others
with the same request to find the correct ticket.
</li>
-</ol> \ No newline at end of file
+</ol>
+
diff --git a/chrome/common/extensions/docs/static/getstarted.html b/chrome/common/extensions/docs/static/getstarted.html
index 497652c..e1b907e 100644
--- a/chrome/common/extensions/docs/static/getstarted.html
+++ b/chrome/common/extensions/docs/static/getstarted.html
@@ -59,15 +59,13 @@ to the toolbar of Google Chrome.
</li>
<li id="load-ext"> Load the extension.
<ol type="a">
- <li>
+ <li style="margin-top:0" />
Bring up the extensions management page
- by clicking the Tools menu
- <img src="images/toolsmenu.gif" width="43" height="34" alt=""
- align="absmiddle" style="margin:0; padding:0">
- (or the Window menu on Mac)
- and choosing <b>Extensions</b>.
- (If you're using version 6 or later,
- choose <b>Tools > Extensions</b>.)
+ by clicking the wrench icon
+ <img src="images/toolsmenu.gif" width="29" height="29" alt=""
+ style="margin-top:0" />
+ and choosing <b>Tools > Extensions</b>.
+ (On Mac, use <b>Window > Extensions</b>.)
</li>
<li>
diff --git a/chrome/common/extensions/docs/static/i18n.html b/chrome/common/extensions/docs/static/i18n.html
index 207ab3e..c56abc6 100644
--- a/chrome/common/extensions/docs/static/i18n.html
+++ b/chrome/common/extensions/docs/static/i18n.html
@@ -462,7 +462,7 @@ Here's how to change the locale using the UI on Google Chrome for Windows:
</p>
<ol>
- <li> Tools menu (wrench) > <b>Options</b> </li>
+ <li> Wrench icon > <b>Options</b> </li>
<li> Choose the <b>Under the Hood</b> tab </li>
<li> Scroll down to <b>Web Content</b> </li>
<li> Click <b>Change font and language settings</b> </li>
diff --git a/chrome/common/extensions/docs/static/management.html b/chrome/common/extensions/docs/static/management.html
index 11bdc96..f9ee486 100644
--- a/chrome/common/extensions/docs/static/management.html
+++ b/chrome/common/extensions/docs/static/management.html
@@ -1,6 +1,23 @@
<div id="pageData-name" class="pageData">Management</div>
+
<!-- BEGIN AUTHORED CONTENT -->
<p id="classSummary">
The <code>chrome.management</code> module provides ways to manage the list of extensions/apps that are installed and running. It is particularly useful for extensions that <a href="override.html">override</a> the built-in New Tab page.
</p>
+
+<h2 id="manifest">Manifest</h2>
+
+<p>You must declare the "management" permission
+in the <a href="manifest.html">extension manifest</a>
+to use the management API.
+For example:</p>
+<pre>{
+ "name": "My extension",
+ ...
+ <b>"permissions": [
+ "management"
+ ]</b>,
+ ...
+}</pre>
+
<!-- END AUTHORED CONTENT -->
diff --git a/chrome/common/extensions/docs/static/manifest.html b/chrome/common/extensions/docs/static/manifest.html
index 5e1758c..bbefe61 100644
--- a/chrome/common/extensions/docs/static/manifest.html
+++ b/chrome/common/extensions/docs/static/manifest.html
@@ -37,13 +37,14 @@ are <b>name</b> and <b>version</b>.
"<a href="background_pages.html">background_page</a>": "<em>aFile</em>.html",
"<a href="override.html">chrome_url_overrides</a>": {...},
"<a href="content_scripts.html">content_scripts</a>": [...],
+ "<a href="#homepage_url">homepage_url</a>": "http://<em>path/to/homepage</em>",
+ "<a href="#incognito">incognito</a>": "spanning" <em>or</em> "split",
"<a href="#key">key</a>": "<em>publicKey</em>",
"<a href="#minimum_chrome_version">minimum_chrome_version</a>": "<em>versionString</em>",
"<a href="options.html">options_page</a>": "<em>aFile</em>.html",
"<a href="#permissions">permissions</a>": [...],
"<a href="npapi.html">plugins</a>": [...],
"<a href="autoupdate.html">update_url</a>": "http://<em>path/to/updateInfo</em>.xml"
- "<a href="#incognito">incognito</a>": "<em>split</em> or <em>spanning</em>",
}
</pre>
@@ -57,6 +58,19 @@ with links to where they're described in detail,
see the <a href="#overview">Field summary</a>.
</p>
+<h3 id="default_locale">default_locale</h3>
+
+<p>
+Specifies the subdirectory of <code>_locales</code>
+that contains the default strings for this extension.
+This field is <b>required</b> in extensions
+that have a <code>_locales</code> directory;
+it <b>must be absent</b> in extensions
+that have no <code>_locales</code> directory.
+For details, see
+<a href="i18n.html">Internationalization</a>.
+</p>
+
<h3 id="description">description</h3>
<p>
@@ -71,6 +85,15 @@ You can specify locale-specific strings for this field;
see <a href="i18n.html">Internationalization</a> for details.
</p>
+<h3 id="homepage_url">homepage_url</h3>
+
+<p>
+The URL of the homepage for this extension. The extensions management page (chrome://extensions)
+will contain a link to this URL. This field is particularly useful if you
+<a href="hosting.html">host the extension on your own site</a>. If you distribute your
+extension using the <a href="http://chrome.google.com/extensions">gallery</a>,
+the homepage URL defaults to the extension's own gallery page.
+</p>
<h3 id="icons">icons</h3>
@@ -116,8 +139,6 @@ extension developers are using the documented sizes. If you use other sizes,
your icon may look bad in future versions of the browser.
</p>
-
-
<p>
If you submit your extension to the
<a href="https://chrome.google.com/extensions">gallery</a>,
@@ -129,17 +150,35 @@ see the
<a href="http://www.google.com/support/chrome/bin/answer.py?answer=113909">gallery help</a>.
</p>
-<h3 id="default_locale">default_locale</h3>
+<h3 id="incognito">incognito</h3>
<p>
-Specifies the subdirectory of <code>_locales</code>
-that contains the default strings for this extension.
-This field is <b>required</b> in extensions
-that have a <code>_locales</code> directory;
-it <b>must be absent</b> in extensions
-that have no <code>_locales</code> directory.
-For details, see
-<a href="i18n.html">Internationalization</a>.
+Either "spanning" or "split", to specify how this extension will
+behave if allowed to run in incognito mode.
+</p>
+
+<p>
+The default for extensions is "spanning", which means that the extension
+will run in a single shared process. Any events or messages from an incognito
+tab will be sent to the shared process, with an <em>incognito</em> flag
+indicating where it came from.
+</p>
+
+<p>
+The default for installable web apps is "split",
+which means that all app pages in
+an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process.
+This incognito process runs along side the regular process, but has a separate
+memory-only cookie store. Each process sees events and messages only from its
+own context (for example, the incognito process will see only incognito tab updates).
+The processes are unable to communicate with each other.
+</p>
+
+<p>
+As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use
+<em>split</em> incognito behavior. If your extension or app needs to be logged
+into a remote server or persist settings locally, use <em>spanning</em>
+incognito behavior.
</p>
<h3 id="key">key</h3>
@@ -296,6 +335,11 @@ The following table lists the permissions an extension can use.
<a href="idle.html">chrome.idle</a> module. </td>
</tr>
<tr>
+ <td> "management" </td>
+ <td> Required if the extension uses the
+ <a href="management.html">chrome.management</a> module. </td>
+</tr>
+<tr>
<td> "notifications" </td>
<td> Allows the extension to use the proposed HTML5
<a href="http://www.chromium.org/developers/design-documents/desktop-notifications/api-specification">notification API</a>
@@ -315,7 +359,16 @@ The following table lists the permissions an extension can use.
<td> Provides an unlimited quota for storing HTML5 client-side data,
such as databases and local storage files.
Without this permission, the extension is limited to
- 5 MB of local storage. </td>
+ 5 MB of local storage.
+
+ <p class="note">
+ <b>Note:</b>
+ This permission applies only to Web SQL Database and application cache
+ (see issue <a href="http://crbug.com/58985">58985</a>).
+ Also, it doesn't currently work with wildcard subdomains such as
+ <code>http://*.example.com</code>.
+ </p>
+ </td>
</tr>
</table>
@@ -369,34 +422,4 @@ For more information, see
<a href="autoupdate.html">Autoupdating</a>.
</p>
-<h3 id="incognito">incognito</h3>
-
-<p>
-Either <em>split</em> or <em>spanning</em>, to specify how this extension will
-behave if allowed to run in incognito.
-</p>
-
-<p>
-<em>spanning</em> is the default for extensions, and means that the extension
-will run in a single shared process. Any events or messages from an incognito
-tab will be sent to the shared process, with an <em>incognito</em> flag
-indicating where it came from.
-</p>
-
-<p>
-<em>split</em> is the default for apps, and it means that all app pages in
-an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process.
-This incognito process runs along side the regular process, but has a separate
-memory-only cookie store. Each process sees events and messages only from its
-own context (e.g. the incognito process will only see incognito tab updates).
-The processes are unable to communicate with each other.
-</p>
-
-<p>
-As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use
-<em>split</em> incognito behavior. If your extension or app needs to be logged
-into a remote server or persist settings locally, use <em>spanning</em>
-incognito behavior.
-</p>
-
<!-- [PENDING: Possibly: point to the gallery and make a big deal of the fact that autoupdating is free if you use the gallery.] -->
diff --git a/chrome/common/extensions/docs/static/override.html b/chrome/common/extensions/docs/static/override.html
index a04b5de..6a4848d 100644
--- a/chrome/common/extensions/docs/static/override.html
+++ b/chrome/common/extensions/docs/static/override.html
@@ -34,7 +34,7 @@ An extension can replace any one of the following pages:
<li> <b>Bookmark Manager:</b>
The page that appears when the user chooses
the Bookmark Manager menu item
- from the Tools (wrench) menu or, on Mac,
+ from the wrench menu or, on Mac,
the Bookmark Manager item from the Bookmarks menu.
You can also get to this page by entering the URL
<b>chrome://bookmarks</b>.
diff --git a/chrome/common/extensions/docs/tabs.html b/chrome/common/extensions/docs/tabs.html
index 4660e79..9aa03b4 100644
--- a/chrome/common/extensions/docs/tabs.html
+++ b/chrome/common/extensions/docs/tabs.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Tabs - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
@@ -1039,7 +1043,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>A port that can be used to communicate with the content scripts running in the specified tab.</dd>
+ <dd>A port that can be used to communicate with the content scripts running in the specified tab. The port's <a href="extension.html#type-Port">onDisconnect</a> event is fired if the tab closes or does not exist. </dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -1398,6 +1402,64 @@ For other examples and for help in viewing the source code, see
</dd>
</div>
+ </div><div>
+ <div>
+ <dt>
+ <var>pinned</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>boolean</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Whether the tab should be pinned. Defaults to <var>false</var></dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
</div>
</dl>
</dd>
@@ -4342,7 +4404,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The JSON response object sent by the handler of the request.</dd>
+ <dd>The JSON response object sent by the handler of the request. If an error occurs while connecting to the specified tab, the callback will be called with no arguments and <a href="extension.html#property-lastError">chrome.extension.lastError</a> will be set to the error message.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -4370,7 +4432,7 @@ For other examples and for help in viewing the source code, see
</div>
</div>
- </dl>
+ </dl>
</div>
</dd>
@@ -4434,7 +4496,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The JSON response object sent by the handler of the request.</dd>
+ <dd>The JSON response object sent by the handler of the request. If an error occurs while connecting to the specified tab, the callback will be called with no arguments and <a href="extension.html#property-lastError">chrome.extension.lastError</a> will be set to the error message.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -4619,7 +4681,7 @@ For other examples and for help in viewing the source code, see
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>string</span>
+ <span>undefined</span>
<span style="display: none; "></span>
</span>
</span>
@@ -4628,12 +4690,10 @@ For other examples and for help in viewing the source code, see
</em>
</dt>
- <dd class="todo">
+ <dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd style="display: none; ">
- Description of this parameter from the json schema.
- </dd>
+ <dd>A URL to navigate the tab to.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -4688,12 +4748,68 @@ For other examples and for help in viewing the source code, see
</em>
</dt>
- <dd class="todo">
+ <dd class="todo" style="display: none; ">
Undocumented.
</dd>
+ <dd>Whether the tab should be selected.</dd>
<dd style="display: none; ">
- Description of this parameter from the json schema.
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
</dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>pinned</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>boolean</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Whether the tab should be pinned.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -6333,7 +6449,7 @@ For other examples and for help in viewing the source code, see
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional" style="display: none; ">optional</span>
+ <span class="optional">optional</span>
<span class="enum" style="display: none; ">enumerated</span>
<span id="typeTemplate">
<span style="display: none; ">
@@ -6413,7 +6529,65 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>Only specified if the tab's URL changed.</dd>
+ <dd>The tab's URL if it has changed.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>pinned</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>boolean</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The tab's new pinned state.</dd>
<dd style="display: none; ">
This parameter was added in version
<b><span></span></b>.
@@ -6808,6 +6982,64 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
+ <var>pinned</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>boolean</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Whether the tab is pinned.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
+ </div><div>
+ <div>
+ <dt>
<var>url</var>
<em>
diff --git a/chrome/common/extensions/docs/template/api_template.html b/chrome/common/extensions/docs/template/api_template.html
index 75f089d..dd4f074 100644
--- a/chrome/common/extensions/docs/template/api_template.html
+++ b/chrome/common/extensions/docs/template/api_template.html
@@ -64,7 +64,7 @@
</dd>
<!-- FUNCTION PARAMETERS -->
- <dd jsdisplay="isFunction($this) && $this.parameters &&
+ <dd jsdisplay="isFunction($this) && $this.parameters &&
$this.name != 'callback'">
<div transclude="functionParametersTemplate"></div>
</dd>
@@ -78,7 +78,7 @@
<div transclude="valueTemplate">
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -212,6 +212,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/template/page_shell.html b/chrome/common/extensions/docs/template/page_shell.html
index 9980469..fdca7c6 100644
--- a/chrome/common/extensions/docs/template/page_shell.html
+++ b/chrome/common/extensions/docs/template/page_shell.html
@@ -19,6 +19,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
</head>
<body>
</body>
diff --git a/chrome/common/extensions/docs/themes.html b/chrome/common/extensions/docs/themes.html
index 0f4912d..9c46460 100644
--- a/chrome/common/extensions/docs/themes.html
+++ b/chrome/common/extensions/docs/themes.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Themes - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/tut_analytics.html b/chrome/common/extensions/docs/tut_analytics.html
index 6f6dafd..4a09e0e 100644
--- a/chrome/common/extensions/docs/tut_analytics.html
+++ b/chrome/common/extensions/docs/tut_analytics.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Tutorial: Google Analytics - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/tut_debugging.html b/chrome/common/extensions/docs/tut_debugging.html
index 9d62494..dad2b44 100644
--- a/chrome/common/extensions/docs/tut_debugging.html
+++ b/chrome/common/extensions/docs/tut_debugging.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Tutorial: Debugging - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/tut_oauth.html b/chrome/common/extensions/docs/tut_oauth.html
index bab5072..a7b4cb5 100644
--- a/chrome/common/extensions/docs/tut_oauth.html
+++ b/chrome/common/extensions/docs/tut_oauth.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Tutorial: OAuth - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/tutorials.html b/chrome/common/extensions/docs/tutorials.html
index c7bc92d..4d270ac 100644
--- a/chrome/common/extensions/docs/tutorials.html
+++ b/chrome/common/extensions/docs/tutorials.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Tutorials - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/whats_new.html b/chrome/common/extensions/docs/whats_new.html
index 61192cb..86f79b9 100644
--- a/chrome/common/extensions/docs/whats_new.html
+++ b/chrome/common/extensions/docs/whats_new.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>What's New in Extensions? - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/windows.html b/chrome/common/extensions/docs/windows.html
index 97518ea..209fd58 100644
--- a/chrome/common/extensions/docs/windows.html
+++ b/chrome/common/extensions/docs/windows.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Windows - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/docs/xhr.html b/chrome/common/extensions/docs/xhr.html
index 5c0176f..8987f40 100644
--- a/chrome/common/extensions/docs/xhr.html
+++ b/chrome/common/extensions/docs/xhr.html
@@ -15,6 +15,7 @@
</script>
<script type="text/javascript" src="js/api_page_generator.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
+ <script type="text/javascript" src="js/sidebar.js"></script>
<title>Cross-Origin XMLHttpRequest - Google Chrome Extensions - Google Code</title></head>
<body> <div id="gc-container" class="labs">
<div id="devModeWarning">
@@ -94,7 +95,7 @@
<div>
</div>
</div>
- </dl>
+ </dl>
</div>
</div> <!-- /SUBTEMPLATES -->
@@ -225,6 +226,9 @@
<li><h2><a href="samples.html">Samples</a></h2></li>
</ul>
</div>
+ <script>
+ initToggles();
+ </script>
<div class="g-unit" id="gc-pagecontent">
<div id="pageTitle">
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index fbb262f..2bbf99b 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -64,7 +64,7 @@ const int kRSAKeySize = 1024;
static void ConvertHexadecimalToIDAlphabet(std::string* id) {
for (size_t i = 0; i < id->size(); ++i) {
int val;
- if (base::HexStringToInt(id->substr(i, 1), &val))
+ if (base::HexStringToInt(id->begin() + i, id->begin() + i + 1, &val))
(*id)[i] = val + 'a';
else
(*id)[i] = 'a';
@@ -249,45 +249,27 @@ const size_t Extension::kNumHostedAppPermissions =
const char Extension::kOldUnlimitedStoragePermission[] = "unlimited_storage";
//
-// Extension::StaticData
-//
-
-Extension::StaticData::StaticData()
- : incognito_split_mode(false),
- location(INVALID),
- converted_from_user_script(false),
- is_theme(false),
- is_app(false),
- launch_container(extension_misc::LAUNCH_TAB),
- launch_width(0),
- launch_height(0) {
-}
-
-Extension::StaticData::~StaticData() {
-}
-
-//
-// Extension::RuntimeData
+// Extension
//
-Extension::RuntimeData::RuntimeData()
- : background_page_ready(false),
- being_upgraded(false) {
-}
-
-Extension::RuntimeData::~RuntimeData() {
+// static
+scoped_refptr<Extension> Extension::Create(const FilePath& path,
+ Location location,
+ const DictionaryValue& value,
+ bool require_key,
+ std::string* error) {
+ scoped_refptr<Extension> extension = new Extension(path, location);
+ if (!extension->InitFromValue(value, require_key, error))
+ return NULL;
+ return extension;
}
-//
-// Extension
-//
-
// static
int Extension::GetPermissionMessageId(const std::string& permission) {
return ExtensionConfig::GetSingleton()->GetPermissionMessageId(permission);
}
-std::vector<string16> Extension::GetPermissionMessages() {
+std::vector<string16> Extension::GetPermissionMessages() const {
std::vector<string16> messages;
if (!plugins().empty()) {
messages.push_back(
@@ -305,7 +287,7 @@ std::vector<string16> Extension::GetPermissionMessages() {
return messages;
}
-std::set<string16> Extension::GetSimplePermissionMessages() {
+std::set<string16> Extension::GetSimplePermissionMessages() const {
std::set<string16> messages;
std::set<std::string>::const_iterator i;
for (i = api_permissions().begin(); i != api_permissions().end(); ++i) {
@@ -316,7 +298,7 @@ std::set<string16> Extension::GetSimplePermissionMessages() {
return messages;
}
-std::vector<std::string> Extension::GetDistinctHosts() {
+std::vector<std::string> Extension::GetDistinctHosts() const {
return GetDistinctHosts(GetEffectiveHostPermissions().patterns());
}
@@ -347,7 +329,7 @@ std::vector<std::string> Extension::GetDistinctHosts(
return distinct_hosts;
}
-string16 Extension::GetHostPermissionMessage() {
+string16 Extension::GetHostPermissionMessage() const {
if (HasEffectiveAccessToAllHosts())
return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT2_WARNING_ALL_HOSTS);
@@ -401,9 +383,6 @@ bool Extension::IsHostedAppPermission(const std::string& str) {
return false;
}
-Extension::~Extension() {
-}
-
const std::string Extension::VersionString() const {
return version()->GetString();
}
@@ -438,7 +417,7 @@ std::string Extension::GenerateIdForPath(const FilePath& path) {
return id;
}
-Extension::HistogramType Extension::GetHistogramType() {
+Extension::HistogramType Extension::GetHistogramType() const {
if (is_theme())
return TYPE_THEME;
if (converted_from_user_script())
@@ -534,12 +513,11 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
return false;
}
- URLPattern pattern;
+ URLPattern pattern(UserScript::kValidUserScriptSchemes);
if (CanExecuteScriptEverywhere())
- pattern = URLPattern(URLPattern::SCHEME_ALL);
- else
- pattern = URLPattern(UserScript::kValidUserScriptSchemes);
- if (!pattern.Parse(match_str)) {
+ pattern.set_valid_schemes(URLPattern::SCHEME_ALL);
+
+ if (URLPattern::PARSE_SUCCESS != pattern.Parse(match_str)) {
*error = ExtensionErrorUtils::FormatErrorMessage(errors::kInvalidMatch,
base::IntToString(definition_index), base::IntToString(j));
return false;
@@ -774,7 +752,7 @@ ExtensionAction* Extension::LoadExtensionActionHelper(
return result.release();
}
-bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) {
+bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) const {
for (DictionaryValue::key_iterator key = source.begin_keys();
key != source.end_keys(); ++key) {
if (!IsBaseCrxKey(*key) && *key != keys::kTheme)
@@ -786,7 +764,7 @@ bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) {
bool Extension::LoadIsApp(const DictionaryValue* manifest,
std::string* error) {
if (manifest->HasKey(keys::kApp))
- mutable_static_data_->is_app = true;
+ is_app_ = true;
return true;
}
@@ -816,7 +794,12 @@ bool Extension::LoadExtent(const DictionaryValue* manifest,
}
URLPattern pattern(kValidWebExtentSchemes);
- if (!pattern.Parse(pattern_string)) {
+ URLPattern::ParseResult result = pattern.Parse(pattern_string);
+ if (result == URLPattern::PARSE_ERROR_EMPTY_PATH) {
+ pattern_string += "/";
+ result = pattern.Parse(pattern_string);
+ }
+ if (URLPattern::PARSE_SUCCESS != result) {
*error = ExtensionErrorUtils::FormatErrorMessage(value_error,
base::UintToString(i));
return false;
@@ -869,7 +852,7 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest,
return false;
}
- mutable_static_data_->launch_local_path = launch_path;
+ launch_local_path_ = launch_path;
} else if (manifest->Get(keys::kLaunchWebURL, &temp)) {
std::string launch_url;
if (!temp->GetAsString(&launch_url)) {
@@ -883,7 +866,7 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest,
return false;
}
- mutable_static_data_->launch_web_url = launch_url;
+ launch_web_url_ = launch_url;
} else if (is_app()) {
*error = errors::kLaunchURLRequired;
return false;
@@ -899,7 +882,7 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest,
}
pattern.set_host(launch_url.host());
pattern.set_path("/*");
- mutable_static_data_->extent.AddPattern(pattern);
+ extent_.AddPattern(pattern);
}
// In order for the --apps-gallery-url switch to work with the gallery
@@ -909,12 +892,12 @@ bool Extension::LoadLaunchURL(const DictionaryValue* manifest,
GURL gallery_url(CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kAppsGalleryURL));
if (gallery_url.is_valid()) {
- mutable_static_data_->launch_web_url = gallery_url.spec();
+ launch_web_url_ = gallery_url.spec();
URLPattern pattern(URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS);
pattern.Parse(gallery_url.spec());
pattern.set_path(pattern.path() + '*');
- mutable_static_data_->extent.AddPattern(pattern);
+ extent_.AddPattern(pattern);
}
}
@@ -934,9 +917,9 @@ bool Extension::LoadLaunchContainer(const DictionaryValue* manifest,
}
if (launch_container_string == values::kLaunchContainerPanel) {
- mutable_static_data_->launch_container = extension_misc::LAUNCH_PANEL;
+ launch_container_ = extension_misc::LAUNCH_PANEL;
} else if (launch_container_string == values::kLaunchContainerTab) {
- mutable_static_data_->launch_container = extension_misc::LAUNCH_TAB;
+ launch_container_ = extension_misc::LAUNCH_TAB;
} else {
*error = errors::kInvalidLaunchContainer;
return false;
@@ -949,9 +932,9 @@ bool Extension::LoadLaunchContainer(const DictionaryValue* manifest,
*error = errors::kInvalidLaunchWidthContainer;
return false;
}
- if (!temp->GetAsInteger(&mutable_static_data_->launch_width) ||
- mutable_static_data_->launch_width < 0) {
- mutable_static_data_->launch_width = 0;
+ if (!temp->GetAsInteger(&launch_width_) ||
+ launch_width_ < 0) {
+ launch_width_ = 0;
*error = errors::kInvalidLaunchWidth;
return false;
}
@@ -964,9 +947,8 @@ bool Extension::LoadLaunchContainer(const DictionaryValue* manifest,
*error = errors::kInvalidLaunchHeightContainer;
return false;
}
- if (!temp->GetAsInteger(&mutable_static_data_->launch_height) ||
- mutable_static_data_->launch_height < 0) {
- mutable_static_data_->launch_height = 0;
+ if (!temp->GetAsInteger(&launch_height_) || launch_height_ < 0) {
+ launch_height_ = 0;
*error = errors::kInvalidLaunchHeight;
return false;
}
@@ -994,18 +976,22 @@ bool Extension::EnsureNotHybridApp(const DictionaryValue* manifest,
return true;
}
-Extension::Extension(const FilePath& path)
- : mutable_static_data_(new StaticData),
- runtime_data_(new RuntimeData) {
+Extension::Extension(const FilePath& path, Location location)
+ : incognito_split_mode_(false),
+ location_(location),
+ converted_from_user_script_(false),
+ is_theme_(false),
+ is_app_(false),
+ launch_container_(extension_misc::LAUNCH_TAB),
+ launch_width_(0),
+ launch_height_(0) {
DCHECK(path.IsAbsolute());
-
- static_data_ = mutable_static_data_;
- mutable_static_data_->location = INVALID;
-
- mutable_static_data_->path = MaybeNormalizePath(path);
+ path_ = MaybeNormalizePath(path);
}
-
-ExtensionResource Extension::GetResource(const std::string& relative_path) {
+Extension::~Extension() {
+}
+ExtensionResource Extension::GetResource(
+ const std::string& relative_path) const {
#if defined(OS_POSIX)
FilePath relative_file_path(relative_path);
#elif defined(OS_WIN)
@@ -1014,7 +1000,8 @@ ExtensionResource Extension::GetResource(const std::string& relative_path) {
return ExtensionResource(id(), path(), relative_file_path);
}
-ExtensionResource Extension::GetResource(const FilePath& relative_file_path) {
+ExtensionResource Extension::GetResource(
+ const FilePath& relative_file_path) const {
return ExtensionResource(id(), path(), relative_file_path);
}
@@ -1094,8 +1081,8 @@ bool Extension::FormatPEMForFileOutput(const std::string input,
// extensions that require less permissions than the current version, but then
// we don't silently allow them to go back. In order to fix this, we would need
// to remember the max set of permissions we ever granted a single extension.
-bool Extension::IsPrivilegeIncrease(Extension* old_extension,
- Extension* new_extension) {
+bool Extension::IsPrivilegeIncrease(const Extension* old_extension,
+ const Extension* new_extension) {
// If the old extension had native code access, we don't need to go any
// further. Things can't get any worse.
if (old_extension->plugins().size() > 0)
@@ -1142,7 +1129,7 @@ bool Extension::IsPrivilegeIncrease(Extension* old_extension,
}
// static
-void Extension::DecodeIcon(Extension* extension,
+void Extension::DecodeIcon(const Extension* extension,
Icons icon_size,
scoped_ptr<SkBitmap>* result) {
FilePath icon_path = extension->GetIconResource(
@@ -1195,17 +1182,13 @@ GURL Extension::GetBaseURLFromExtensionId(const std::string& extension_id) {
bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
std::string* error) {
- // Unit tests reuse Extension objects, so we need to reset mutable_static_data
- // when we re-initialize.
- mutable_static_data_ = const_cast<StaticData*>(static_data_.get());
-
if (source.HasKey(keys::kPublicKey)) {
std::string public_key_bytes;
if (!source.GetString(keys::kPublicKey,
- &mutable_static_data_->public_key) ||
- !ParsePEMKeyBytes(mutable_static_data_->public_key,
+ &public_key_) ||
+ !ParsePEMKeyBytes(public_key_,
&public_key_bytes) ||
- !GenerateId(public_key_bytes, &mutable_static_data_->id)) {
+ !GenerateId(public_key_bytes, &id_)) {
*error = errors::kInvalidKey;
return false;
}
@@ -1216,19 +1199,19 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
// If there is a path, we generate the ID from it. This is useful for
// development mode, because it keeps the ID stable across restarts and
// reloading the extension.
- mutable_static_data_->id = Extension::GenerateIdForPath(path());
- if (mutable_static_data_->id.empty()) {
+ id_ = Extension::GenerateIdForPath(path());
+ if (id_.empty()) {
NOTREACHED() << "Could not create ID from path.";
return false;
}
}
// Make a copy of the manifest so we can store it in prefs.
- mutable_static_data_->manifest_value.reset(
+ manifest_value_.reset(
static_cast<DictionaryValue*>(source.DeepCopy()));
// Initialize the URL.
- mutable_static_data_->extension_url =
+ extension_url_ =
Extension::GetBaseURLFromExtensionId(id());
// Initialize version.
@@ -1237,10 +1220,10 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
*error = errors::kInvalidVersion;
return false;
}
- mutable_static_data_->version.reset(
+ version_.reset(
Version::GetVersionFromString(version_str));
- if (!mutable_static_data_->version.get() ||
- mutable_static_data_->version->components().size() > 4) {
+ if (!version_.get() ||
+ version_->components().size() > 4) {
*error = errors::kInvalidVersion;
return false;
}
@@ -1252,17 +1235,33 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
base::i18n::AdjustStringForLocaleDirection(localized_name, &localized_name);
- mutable_static_data_->name = UTF16ToUTF8(localized_name);
+ name_ = UTF16ToUTF8(localized_name);
// Initialize description (if present).
if (source.HasKey(keys::kDescription)) {
if (!source.GetString(keys::kDescription,
- &mutable_static_data_->description)) {
+ &description_)) {
*error = errors::kInvalidDescription;
return false;
}
}
+ // Initialize homepage url (if present).
+ if (source.HasKey(keys::kHomepageURL)) {
+ std::string tmp;
+ if (!source.GetString(keys::kHomepageURL, &tmp)) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidHomepageURL, "");
+ return false;
+ }
+ homepage_url_ = GURL(tmp);
+ if (!homepage_url_.is_valid()) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidHomepageURL, tmp);
+ return false;
+ }
+ }
+
// Initialize update url (if present).
if (source.HasKey(keys::kUpdateURL)) {
std::string tmp;
@@ -1271,9 +1270,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
errors::kInvalidUpdateURL, "");
return false;
}
- mutable_static_data_->update_url = GURL(tmp);
- if (!mutable_static_data_->update_url.is_valid() ||
- mutable_static_data_->update_url.has_ref()) {
+ update_url_ = GURL(tmp);
+ if (!update_url_.is_valid() ||
+ update_url_.has_ref()) {
*error = ExtensionErrorUtils::FormatErrorMessage(
errors::kInvalidUpdateURL, tmp);
return false;
@@ -1321,7 +1320,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
// Initialize converted_from_user_script (if present)
source.GetBoolean(keys::kConvertedFromUserScript,
- &mutable_static_data_->converted_from_user_script);
+ &converted_from_user_script_);
// Initialize icons (if present).
if (source.HasKey(keys::kIcons)) {
@@ -1350,13 +1349,13 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
- mutable_static_data_->icons.Add(kIconSizes[i], icon_path);
+ icons_.Add(kIconSizes[i], icon_path);
}
}
}
// Initialize themes (if present).
- mutable_static_data_->is_theme = false;
+ is_theme_ = false;
if (source.HasKey(keys::kTheme)) {
// Themes cannot contain extension keys.
if (ContainsNonThemeKeys(source)) {
@@ -1369,7 +1368,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
*error = errors::kInvalidTheme;
return false;
}
- mutable_static_data_->is_theme = true;
+ is_theme_ = true;
DictionaryValue* images_value;
if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) {
@@ -1382,7 +1381,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
}
- mutable_static_data_->theme_images.reset(
+ theme_images_.reset(
static_cast<DictionaryValue*>(images_value->DeepCopy()));
}
@@ -1411,7 +1410,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
}
- mutable_static_data_->theme_colors.reset(
+ theme_colors_.reset(
static_cast<DictionaryValue*>(colors_value->DeepCopy()));
}
@@ -1432,14 +1431,14 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
}
- mutable_static_data_->theme_tints.reset(
+ theme_tints_.reset(
static_cast<DictionaryValue*>(tints_value->DeepCopy()));
}
DictionaryValue* display_properties_value;
if (theme_value->GetDictionary(keys::kThemeDisplayProperties,
&display_properties_value)) {
- mutable_static_data_->theme_display_properties.reset(
+ theme_display_properties_.reset(
static_cast<DictionaryValue*>(display_properties_value->DeepCopy()));
}
@@ -1487,9 +1486,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
}
}
- mutable_static_data_->plugins.push_back(PluginInfo());
- mutable_static_data_->plugins.back().path = path().AppendASCII(path_str);
- mutable_static_data_->plugins.back().is_public = is_public;
+ plugins_.push_back(PluginInfo());
+ plugins_.back().path = path().AppendASCII(path_str);
+ plugins_.back().is_public = is_public;
}
}
@@ -1500,7 +1499,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
*error = errors::kInvalidBackground;
return false;
}
- mutable_static_data_->background_url = GetResourceURL(background_str);
+ background_url_ = GetResourceURL(background_str);
}
// Initialize toolstrips. This is deprecated for public use.
@@ -1535,7 +1534,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
errors::kInvalidToolstrip, base::IntToString(i));
return false;
}
- mutable_static_data_->toolstrips.push_back(toolstrip);
+ toolstrips_.push_back(toolstrip);
}
}
@@ -1559,11 +1558,11 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
if (!LoadUserScriptHelper(content_script, i, error, &script))
return false; // Failed to parse script context definition.
script.set_extension_id(id());
- if (mutable_static_data_->converted_from_user_script) {
+ if (converted_from_user_script_) {
script.set_emulate_greasemonkey(true);
script.set_match_all_frames(true); // Greasemonkey matches all frames.
}
- mutable_static_data_->content_scripts.push_back(script);
+ content_scripts_.push_back(script);
}
}
@@ -1600,9 +1599,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
// If page_action_value is not NULL, then there was a valid page action.
if (page_action_value) {
- mutable_static_data_->page_action.reset(
+ page_action_.reset(
LoadExtensionActionHelper(page_action_value, error));
- if (!mutable_static_data_->page_action.get())
+ if (!page_action_.get())
return false; // Failed to parse page action definition.
}
@@ -1614,25 +1613,25 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
- mutable_static_data_->browser_action.reset(
+ browser_action_.reset(
LoadExtensionActionHelper(browser_action_value, error));
- if (!mutable_static_data_->browser_action.get())
+ if (!browser_action_.get())
return false; // Failed to parse browser action definition.
}
// Load App settings.
- if (!LoadIsApp(mutable_static_data_->manifest_value.get(), error) ||
- !LoadExtent(mutable_static_data_->manifest_value.get(), keys::kWebURLs,
- &mutable_static_data_->extent,
+ if (!LoadIsApp(manifest_value_.get(), error) ||
+ !LoadExtent(manifest_value_.get(), keys::kWebURLs,
+ &extent_,
errors::kInvalidWebURLs, errors::kInvalidWebURL, error) ||
- !EnsureNotHybridApp(mutable_static_data_->manifest_value.get(), error) ||
- !LoadLaunchURL(mutable_static_data_->manifest_value.get(), error) ||
- !LoadLaunchContainer(mutable_static_data_->manifest_value.get(), error)) {
+ !EnsureNotHybridApp(manifest_value_.get(), error) ||
+ !LoadLaunchURL(manifest_value_.get(), error) ||
+ !LoadLaunchContainer(manifest_value_.get(), error)) {
return false;
}
// Initialize options page url (optional).
- // Funtion LoadIsApp() set mutable_static_data_->is_app above.
+ // Funtion LoadIsApp() set is_app_ above.
if (source.HasKey(keys::kOptionsPage)) {
std::string options_str;
if (!source.GetString(keys::kOptionsPage, &options_str)) {
@@ -1648,7 +1647,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
*error = errors::kInvalidOptionsPageInHostedApp;
return false;
}
- mutable_static_data_->options_url = options_url;
+ options_url_ = options_url;
} else {
GURL absolute(options_str);
@@ -1656,8 +1655,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
*error = errors::kInvalidOptionsPageExpectUrlInPackage;
return false;
}
- mutable_static_data_->options_url = GetResourceURL(options_str);
- if (!mutable_static_data_->options_url.is_valid()) {
+ options_url_ = GetResourceURL(options_str);
+ if (!options_url_.is_valid()) {
*error = errors::kInvalidOptionsPage;
return false;
}
@@ -1685,7 +1684,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
// TODO(asargent) - We want a more general purpose mechanism for this,
// and better error messages. (http://crbug.com/54013)
if (permission_str == kWebstorePrivatePermission &&
- mutable_static_data_->location != Extension::COMPONENT) {
+ location_ != Extension::COMPONENT) {
continue;
}
@@ -1696,13 +1695,13 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
if (web_extent().is_empty() || location() == Extension::COMPONENT) {
// Check if it's a module permission. If so, enable that permission.
if (IsAPIPermission(permission_str)) {
- mutable_static_data_->api_permissions.insert(permission_str);
+ api_permissions_.insert(permission_str);
continue;
}
} else {
// Hosted apps only get access to a subset of the valid permissions.
if (IsHostedAppPermission(permission_str)) {
- mutable_static_data_->api_permissions.insert(permission_str);
+ api_permissions_.insert(permission_str);
continue;
}
}
@@ -1713,7 +1712,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
(UserScript::kValidUserScriptSchemes |
URLPattern::SCHEME_CHROMEUI) & ~URLPattern::SCHEME_FILE);
- if (!pattern.Parse(permission_str)) {
+ if (URLPattern::PARSE_SUCCESS != pattern.Parse(permission_str)) {
*error = ExtensionErrorUtils::FormatErrorMessage(
errors::kInvalidPermission, base::IntToString(i));
return false;
@@ -1729,14 +1728,14 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
// match all paths.
pattern.set_path("/*");
- mutable_static_data_->host_permissions.push_back(pattern);
+ host_permissions_.push_back(pattern);
}
}
if (source.HasKey(keys::kDefaultLocale)) {
if (!source.GetString(keys::kDefaultLocale,
- &mutable_static_data_->default_locale) ||
- mutable_static_data_->default_locale.empty()) {
+ &default_locale_) ||
+ default_locale_.empty()) {
*error = errors::kInvalidDefaultLocale;
return false;
}
@@ -1767,7 +1766,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
// Replace the entry with a fully qualified chrome-extension:// URL.
- mutable_static_data_->chrome_url_overrides[page] = GetResourceURL(val);
+ chrome_url_overrides_[page] = GetResourceURL(val);
}
// An extension may override at most one page.
@@ -1779,8 +1778,8 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
if (source.HasKey(keys::kOmniboxKeyword)) {
if (!source.GetString(keys::kOmniboxKeyword,
- &mutable_static_data_->omnibox_keyword) ||
- mutable_static_data_->omnibox_keyword.empty()) {
+ &omnibox_keyword_) ||
+ omnibox_keyword_.empty()) {
*error = errors::kInvalidOmniboxKeyword;
return false;
}
@@ -1801,12 +1800,12 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
*error = errors::kDevToolsExperimental;
return false;
}
- mutable_static_data_->devtools_url = GetResourceURL(devtools_str);
+ devtools_url_ = GetResourceURL(devtools_str);
}
// Initialize incognito behavior. Apps default to split mode, extensions
// default to spanning.
- mutable_static_data_->incognito_split_mode = is_app();
+ incognito_split_mode_ = is_app();
if (source.HasKey(keys::kIncognito)) {
std::string value;
if (!source.GetString(keys::kIncognito, &value)) {
@@ -1814,9 +1813,9 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
return false;
}
if (value == values::kIncognitoSpanning) {
- mutable_static_data_->incognito_split_mode = false;
+ incognito_split_mode_ = false;
} else if (value == values::kIncognitoSplit) {
- mutable_static_data_->incognito_split_mode = true;
+ incognito_split_mode_ = true;
} else {
*error = errors::kInvalidIncognitoBehavior;
return false;
@@ -1835,10 +1834,7 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key,
// it calls InitFromValue, passing it up to the browser process which calls
// InitFromValue again. As a result, we need to make sure that nobody
// accidentally modifies it.
- DCHECK(source.Equals(mutable_static_data_->manifest_value.get()));
-
- // Ensure we can't modify our static data anymore.
- mutable_static_data_ = NULL;
+ DCHECK(source.Equals(manifest_value_.get()));
return true;
}
@@ -1854,19 +1850,22 @@ std::string Extension::ChromeStoreLaunchURL() {
return gallery_prefix;
}
-GURL Extension::GalleryUrl() const {
- if (!update_url().DomainIs("google.com"))
+GURL Extension::GetHomepageURL() const {
+ if (homepage_url_.is_valid())
+ return homepage_url_;
+
+ if (update_url()!= GURL(extension_urls::kGalleryUpdateHttpsUrl) &&
+ update_url()!= GURL(extension_urls::kGalleryUpdateHttpUrl))
return GURL();
// TODO(erikkay): This may not be entirely correct with the webstore.
// I think it will have a mixture of /extensions/detail and /webstore/detail
// URLs. Perhaps they'll handle this nicely with redirects?
GURL url(ChromeStoreLaunchURL() + std::string("/detail/") + id());
-
return url;
}
-std::set<FilePath> Extension::GetBrowserImages() {
+std::set<FilePath> Extension::GetBrowserImages() const {
std::set<FilePath> image_paths;
// TODO(viettrungluu): These |FilePath::FromWStringHack(UTF8ToWide())|
// indicate that we're doing something wrong.
@@ -1916,20 +1915,6 @@ GURL Extension::GetFullLaunchURL() const {
return GURL(launch_web_url());
}
-bool Extension::GetBackgroundPageReady() {
- return (GetRuntimeData()->background_page_ready ||
- background_url().is_empty());
-}
-
-void Extension::SetBackgroundPageReady() {
- DCHECK(!background_url().is_empty());
- GetRuntimeData()->background_page_ready = true;
- NotificationService::current()->Notify(
- NotificationType::EXTENSION_BACKGROUND_PAGE_READY,
- Source<Extension>(this),
- NotificationService::NoDetails());
-}
-
static std::string SizeToString(const gfx::Size& max_size) {
return base::IntToString(max_size.width()) + "x" +
base::IntToString(max_size.height());
@@ -1949,29 +1934,27 @@ void Extension::SetScriptingWhitelist(
void Extension::SetCachedImage(const ExtensionResource& source,
const SkBitmap& image,
- const gfx::Size& original_size) {
+ const gfx::Size& original_size) const {
DCHECK(source.extension_root() == path()); // The resource must come from
// this extension.
const FilePath& path = source.relative_path();
gfx::Size actual_size(image.width(), image.height());
if (actual_size == original_size) {
- GetRuntimeData()->image_cache_[
- RuntimeData::ImageCacheKey(path, std::string())] = image;
+ image_cache_[ImageCacheKey(path, std::string())] = image;
} else {
- GetRuntimeData()->image_cache_[
- RuntimeData::ImageCacheKey(path, SizeToString(actual_size))] = image;
+ image_cache_[ImageCacheKey(path, SizeToString(actual_size))] = image;
}
}
bool Extension::HasCachedImage(const ExtensionResource& source,
- const gfx::Size& max_size) {
+ const gfx::Size& max_size) const {
DCHECK(source.extension_root() == path()); // The resource must come from
// this extension.
return GetCachedImageImpl(source, max_size) != NULL;
}
SkBitmap Extension::GetCachedImage(const ExtensionResource& source,
- const gfx::Size& max_size) {
+ const gfx::Size& max_size) const {
DCHECK(source.extension_root() == path()); // The resource must come from
// this extension.
SkBitmap* image = GetCachedImageImpl(source, max_size);
@@ -1979,20 +1962,19 @@ SkBitmap Extension::GetCachedImage(const ExtensionResource& source,
}
SkBitmap* Extension::GetCachedImageImpl(const ExtensionResource& source,
- const gfx::Size& max_size) {
+ const gfx::Size& max_size) const {
const FilePath& path = source.relative_path();
// Look for exact size match.
- RuntimeData::ImageCache::iterator i = GetRuntimeData()->image_cache_.find(
- RuntimeData::ImageCacheKey(path, SizeToString(max_size)));
- if (i != GetRuntimeData()->image_cache_.end())
+ ImageCache::iterator i = image_cache_.find(
+ ImageCacheKey(path, SizeToString(max_size)));
+ if (i != image_cache_.end())
return &(i->second);
// If we have the original size version cached, return that if it's small
// enough.
- i = GetRuntimeData()->image_cache_.find(
- RuntimeData::ImageCacheKey(path, std::string()));
- if (i != GetRuntimeData()->image_cache_.end()) {
+ i = image_cache_.find(ImageCacheKey(path, std::string()));
+ if (i != image_cache_.end()) {
SkBitmap& image = i->second;
if (image.width() <= max_size.width() &&
image.height() <= max_size.height())
@@ -2003,14 +1985,15 @@ SkBitmap* Extension::GetCachedImageImpl(const ExtensionResource& source,
}
ExtensionResource Extension::GetIconResource(
- int size, ExtensionIconSet::MatchType match_type) {
+ int size, ExtensionIconSet::MatchType match_type) const {
std::string path = icons().Get(size, match_type);
if (path.empty())
return ExtensionResource();
return GetResource(path);
}
-GURL Extension::GetIconURL(int size, ExtensionIconSet::MatchType match_type) {
+GURL Extension::GetIconURL(int size,
+ ExtensionIconSet::MatchType match_type) const {
std::string path = icons().Get(size, match_type);
if (path.empty())
return GURL();
@@ -2018,7 +2001,7 @@ GURL Extension::GetIconURL(int size, ExtensionIconSet::MatchType match_type) {
return GetResourceURL(path);
}
-bool Extension::CanSpecifyHostPermission(const URLPattern pattern) const {
+bool Extension::CanSpecifyHostPermission(const URLPattern& pattern) const {
if (!pattern.match_all_urls() &&
pattern.MatchesScheme(chrome::kChromeUIScheme)) {
// Only allow access to chrome://favicon to regular extensions. Component
@@ -2031,7 +2014,7 @@ bool Extension::CanSpecifyHostPermission(const URLPattern pattern) const {
return true;
}
-// static.
+// static
bool Extension::HasApiPermission(
const std::set<std::string>& api_permissions,
const std::string& function_name) {
@@ -2077,7 +2060,7 @@ bool Extension::HasHostPermission(const GURL& url) const {
void Extension::InitEffectiveHostPermissions() {
for (URLPatternList::const_iterator host = host_permissions().begin();
host != host_permissions().end(); ++host)
- mutable_static_data_->effective_host_permissions.AddPattern(*host);
+ effective_host_permissions_.AddPattern(*host);
for (UserScriptList::const_iterator content_script =
content_scripts().begin();
@@ -2085,7 +2068,7 @@ void Extension::InitEffectiveHostPermissions() {
UserScript::PatternList::const_iterator pattern =
content_script->url_patterns().begin();
for (; pattern != content_script->url_patterns().end(); ++pattern)
- mutable_static_data_->effective_host_permissions.AddPattern(*pattern);
+ effective_host_permissions_.AddPattern(*pattern);
}
}
@@ -2171,7 +2154,7 @@ bool Extension::HasEffectiveAccessToAllHosts() const {
return false;
}
-bool Extension::IsAPIPermission(const std::string& str) {
+bool Extension::IsAPIPermission(const std::string& str) const {
for (size_t i = 0; i < Extension::kNumPermissions; ++i) {
if (str == Extension::kPermissions[i].name) {
// Only allow the experimental API permission if the command line
@@ -2210,12 +2193,6 @@ bool Extension::CanExecuteScriptEverywhere() const {
return false;
}
-Extension::RuntimeData* Extension::GetRuntimeData() const {
- // TODO(mpcomplete): it would be nice if I could verify we were on the UI
- // thread, but we're in common and don't have access to BrowserThread.
- return const_cast<Extension::RuntimeData*>(runtime_data_.get());
-}
-
ExtensionInfo::ExtensionInfo(const DictionaryValue* manifest,
const std::string& id,
const FilePath& path,
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index db1c0c3..ce7e628 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -30,7 +30,7 @@ class SkBitmap;
class Version;
// Represents a Chrome extension.
-class Extension {
+class Extension : public base::RefCountedThreadSafe<Extension> {
public:
typedef std::map<const std::string, GURL> URLOverrideMap;
typedef std::vector<std::string> ScriptingWhitelist;
@@ -49,8 +49,12 @@ class Extension {
COMPONENT, // An integral component of Chrome itself, which
// happens to be implemented as an extension. We don't
// show these in the management UI.
- EXTERNAL_PREF_DOWNLOAD // A crx file from an external directory (via
+ EXTERNAL_PREF_DOWNLOAD, // A crx file from an external directory (via
// prefs), installed from an update URL.
+ EXTERNAL_POLICY_DOWNLOAD, // A crx file from an external directory (via
+ // admin policies), installed from an update URL.
+
+ NUM_LOCATIONS
};
enum State {
@@ -96,181 +100,6 @@ class Extension {
bool is_public; // False if only this extension can load this plugin.
};
- // Contains a subset of the extension's data that doesn't change once
- // initialized, and therefore shareable across threads without locking.
- struct StaticData : public base::RefCountedThreadSafe<StaticData> {
- StaticData();
-
- // TODO(mpcomplete): RefCountedThreadSafe does not allow AddRef/Release on
- // const objects. I think that is a mistake. Until we can fix that, here's
- // a workaround.
- void AddRef() const {
- const_cast<StaticData*>(this)->
- base::RefCountedThreadSafe<StaticData>::AddRef();
- }
- void Release() const {
- const_cast<StaticData*>(this)->
- base::RefCountedThreadSafe<StaticData>::Release();
- }
-
- // A persistent, globally unique ID. An extension's ID is used in things
- // like directory structures and URLs, and is expected to not change across
- // versions. It is generated as a SHA-256 hash of the extension's public
- // key, or as a hash of the path in the case of unpacked extensions.
- std::string id;
-
- // The extension's human-readable name. Name is used for display purpose. It
- // might be wrapped with unicode bidi control characters so that it is
- // displayed correctly in RTL context.
- // NOTE: Name is UTF-8 and may contain non-ascii characters.
- std::string name;
-
- // The absolute path to the directory the extension is stored in.
- FilePath path;
-
- // Default locale for fall back. Can be empty if extension is not localized.
- std::string default_locale;
-
- // If true, a separate process will be used for the extension in incognito
- // mode.
- bool incognito_split_mode;
-
- // Defines the set of URLs in the extension's web content.
- ExtensionExtent extent;
-
- // The set of host permissions that the extension effectively has access to,
- // which is a merge of host_permissions_ and all of the match patterns in
- // any content scripts the extension has. This is used to determine which
- // URLs have the ability to load an extension's resources via embedded
- // chrome-extension: URLs (see extension_protocols.cc).
- ExtensionExtent effective_host_permissions;
-
- // The set of module-level APIs this extension can use.
- std::set<std::string> api_permissions;
-
- // The icons for the extension.
- ExtensionIconSet icons;
-
- // The base extension url for the extension.
- GURL extension_url;
-
- // The location the extension was loaded from.
- Location location;
-
- // The extension's version.
- scoped_ptr<Version> version;
-
- // An optional longer description of the extension.
- std::string description;
-
- // True if the extension was generated from a user script. (We show slightly
- // different UI if so).
- bool converted_from_user_script;
-
- // Paths to the content scripts the extension contains.
- UserScriptList content_scripts;
-
- // The extension's page action, if any.
- scoped_ptr<ExtensionAction> page_action;
-
- // The extension's browser action, if any.
- scoped_ptr<ExtensionAction> browser_action;
-
- // Optional list of NPAPI plugins and associated properties.
- std::vector<PluginInfo> plugins;
-
- // Optional URL to a master page of which a single instance should be always
- // loaded in the background.
- GURL background_url;
-
- // Optional URL to a page for setting options/preferences.
- GURL options_url;
-
- // Optional URL to a devtools extension page.
- GURL devtools_url;
-
- // Optional list of toolstrips and associated properties.
- std::vector<GURL> toolstrips;
-
- // The public key used to sign the contents of the crx package.
- std::string public_key;
-
- // A map of resource id's to relative file paths.
- scoped_ptr<DictionaryValue> theme_images;
-
- // A map of color names to colors.
- scoped_ptr<DictionaryValue> theme_colors;
-
- // A map of color names to colors.
- scoped_ptr<DictionaryValue> theme_tints;
-
- // A map of display properties.
- scoped_ptr<DictionaryValue> theme_display_properties;
-
- // Whether the extension is a theme.
- bool is_theme;
-
- // The sites this extension has permission to talk to (using XHR, etc).
- URLPatternList host_permissions;
-
- // URL for fetching an update manifest
- GURL update_url;
-
- // A copy of the manifest that this extension was created from.
- scoped_ptr<DictionaryValue> manifest_value;
-
- // A map of chrome:// hostnames (newtab, downloads, etc.) to Extension URLs
- // which override the handling of those URLs.
- URLOverrideMap chrome_url_overrides;
-
- // Whether this extension uses app features.
- bool is_app;
-
- // The local path inside the extension to use with the launcher.
- std::string launch_local_path;
-
- // A web url to use with the launcher. Note that this might be relative or
- // absolute. If relative, it is relative to web_origin.
- std::string launch_web_url;
-
- // The type of container to launch into.
- extension_misc::LaunchContainer launch_container;
-
- // The default size of the container when launching. Only respected for
- // containers like panels and windows.
- int launch_width;
- int launch_height;
-
- // The Omnibox keyword for this extension, or empty if there is none.
- std::string omnibox_keyword;
-
- protected:
- friend class base::RefCountedThreadSafe<StaticData>;
- ~StaticData();
- };
-
- // Contains the subset of the extension's (private) data that can be modified
- // after initialization. This class should only be accessed on the UI thread.
- struct RuntimeData {
- // We keep a cache of images loaded from extension resources based on their
- // path and a string representation of a size that may have been used to
- // scale it (or the empty string if the image is at its original size).
- typedef std::pair<FilePath, std::string> ImageCacheKey;
- typedef std::map<ImageCacheKey, SkBitmap> ImageCache;
-
- RuntimeData();
- ~RuntimeData();
-
- // True if the background page is ready.
- bool background_page_ready;
-
- // True while the extension is being upgraded.
- bool being_upgraded;
-
- // Cached images for this extension.
- ImageCache image_cache_;
- };
-
// A permission is defined by its |name| (what is used in the manifest),
// and the |message_id| that's used by install/update UI.
struct Permission {
@@ -278,12 +107,18 @@ class Extension {
const int message_id;
};
+ static scoped_refptr<Extension> Create(const FilePath& path,
+ Location location,
+ const DictionaryValue& value,
+ bool require_key,
+ std::string* error);
+
// The install message id for |permission|. Returns 0 if none exists.
static int GetPermissionMessageId(const std::string& permission);
// Returns the full list of permission messages that this extension
// should display at install time.
- std::vector<string16> GetPermissionMessages();
+ std::vector<string16> GetPermissionMessages() const;
// Returns the distinct hosts that should be displayed in the install UI. This
// discards some of the detail that is present in the manifest to make it as
@@ -291,7 +126,7 @@ class Extension {
// and path components of URLPatterns and de-dupe the result.
static std::vector<std::string> GetDistinctHosts(
const URLPatternList& host_patterns);
- std::vector<std::string> GetDistinctHosts();
+ std::vector<std::string> GetDistinctHosts() const;
// Icon sizes used by the extension system.
static const int kIconSizes[];
@@ -351,9 +186,6 @@ class Extension {
// The mimetype used for extensions.
static const char kMimeType[];
- explicit Extension(const FilePath& path);
- virtual ~Extension();
-
// Checks to see if the extension has a valid ID.
static bool IdIsValid(const std::string& id);
@@ -367,11 +199,19 @@ class Extension {
static inline bool IsExternalLocation(Location location) {
return location == Extension::EXTERNAL_PREF ||
location == Extension::EXTERNAL_REGISTRY ||
- location == Extension::EXTERNAL_PREF_DOWNLOAD;
+ location == Extension::EXTERNAL_PREF_DOWNLOAD ||
+ location == Extension::EXTERNAL_POLICY_DOWNLOAD;
+ }
+
+ // Whether extensions with |location| are auto-updatable or not.
+ static inline bool IsAutoUpdateableLocation(Location location) {
+ // Only internal and external extensions can be autoupdated.
+ return location == Extension::INTERNAL ||
+ IsExternalLocation(location);
}
// See HistogramType definition above.
- HistogramType GetHistogramType();
+ HistogramType GetHistogramType() const;
// Returns an absolute url to a resource inside of an extension. The
// |extension_url| argument should be the url() from an Extension object. The
@@ -386,10 +226,10 @@ class Extension {
// Returns an extension resource object. |relative_path| should be UTF8
// encoded.
- ExtensionResource GetResource(const std::string& relative_path);
+ ExtensionResource GetResource(const std::string& relative_path) const;
// As above, but with |relative_path| following the file system's encoding.
- ExtensionResource GetResource(const FilePath& relative_path);
+ ExtensionResource GetResource(const FilePath& relative_path) const;
// |input| is expected to be the text of an rsa public or private key. It
// tolerates the presence or absence of bracking header/footer like this:
@@ -411,14 +251,14 @@ class Extension {
// Determine whether |new_extension| has increased privileges compared to
// |old_extension|.
- static bool IsPrivilegeIncrease(Extension* old_extension,
- Extension* new_extension);
+ static bool IsPrivilegeIncrease(const Extension* old_extension,
+ const Extension* new_extension);
// Given an extension and icon size, read it if present and decode it into
// result. In the browser process, this will DCHECK if not called on the
// file thread. To easily load extension images on the UI thread, see
// ImageLoadingTracker.
- static void DecodeIcon(Extension* extension,
+ static void DecodeIcon(const Extension* extension,
Icons icon_size,
scoped_ptr<SkBitmap>* result);
@@ -457,57 +297,6 @@ class Extension {
// Adds an extension to the scripting whitelist. Used for testing only.
static void SetScriptingWhitelist(const ScriptingWhitelist& whitelist);
- // Initialize the extension from a parsed manifest.
- // Usually, the id of an extension is generated by the "key" property of
- // its manifest, but if |require_key| is |false|, a temporary ID will be
- // generated based on the path.
- bool InitFromValue(const DictionaryValue& value, bool require_key,
- std::string* error);
-
- const StaticData* static_data() const { return static_data_; }
-
- const FilePath& path() const { return static_data_->path; }
- const GURL& url() const { return static_data_->extension_url; }
- Location location() const { return static_data_->location; }
- void set_location(Location location) {
- mutable_static_data_->location = location;
- }
-
- const std::string& id() const { return static_data_->id; }
- const Version* version() const { return static_data_->version.get(); }
- // String representation of the version number.
- const std::string VersionString() const;
- const std::string& name() const { return static_data_->name; }
- const std::string& public_key() const { return static_data_->public_key; }
- const std::string& description() const { return static_data_->description; }
- bool converted_from_user_script() const {
- return static_data_->converted_from_user_script;
- }
- const UserScriptList& content_scripts() const {
- return static_data_->content_scripts;
- }
- ExtensionAction* page_action() const {
- return static_data_->page_action.get();
- }
- ExtensionAction* browser_action() const {
- return static_data_->browser_action.get();
- }
- const std::vector<PluginInfo>& plugins() const {
- return static_data_->plugins;
- }
- const GURL& background_url() const { return static_data_->background_url; }
- const GURL& options_url() const { return static_data_->options_url; }
- const GURL& devtools_url() const { return static_data_->devtools_url; }
- const std::vector<GURL>& toolstrips() const {
- return static_data_->toolstrips;
- }
- const std::set<std::string>& api_permissions() const {
- return static_data_->api_permissions;
- }
- const URLPatternList& host_permissions() const {
- return static_data_->host_permissions;
- }
-
// Returns true if the extension has the specified API permission.
static bool HasApiPermission(const std::set<std::string>& api_permissions,
const std::string& function_name);
@@ -517,14 +306,14 @@ class Extension {
}
const ExtensionExtent& GetEffectiveHostPermissions() const {
- return static_data_->effective_host_permissions;
+ return effective_host_permissions_;
}
// Whether or not the extension is allowed permission for a URL pattern from
// the manifest. http, https, and chrome://favicon/ is allowed for all
// extensions, while component extensions are allowed access to
// chrome://resources.
- bool CanSpecifyHostPermission(const URLPattern pattern) const;
+ bool CanSpecifyHostPermission(const URLPattern& pattern) const;
// Whether the extension has access to the given URL.
bool HasHostPermission(const GURL& url) const;
@@ -536,120 +325,125 @@ class Extension {
// network, etc.)
bool HasEffectiveAccessToAllHosts() const;
- const GURL& update_url() const { return static_data_->update_url; }
-
- const ExtensionIconSet& icons() const {
- return static_data_->icons;
- }
-
- // Returns the Google Gallery URL for this extension, if one exists. For
+ // Returns the Homepage URL for this extension. If homepage_url was not
+ // specified in the manifest, this returns the Google Gallery URL. For
// third-party extensions, this returns a blank GURL.
- GURL GalleryUrl() const;
-
- // Theme-related.
- DictionaryValue* GetThemeImages() const {
- return static_data_->theme_images.get();
- }
- DictionaryValue* GetThemeColors() const {
- return static_data_->theme_colors.get();
- }
- DictionaryValue* GetThemeTints() const {
- return static_data_->theme_tints.get();
- }
- DictionaryValue* GetThemeDisplayProperties() const {
- return static_data_->theme_display_properties.get();
- }
- bool is_theme() const { return static_data_->is_theme; }
+ GURL GetHomepageURL() const;
// Returns a list of paths (relative to the extension dir) for images that
// the browser might load (like themes and page action icons).
- std::set<FilePath> GetBrowserImages();
+ std::set<FilePath> GetBrowserImages() const;
// Get an extension icon as a resource or URL.
- ExtensionResource GetIconResource(int size,
- ExtensionIconSet::MatchType match_type);
- GURL GetIconURL(int size, ExtensionIconSet::MatchType match_type);
-
- const DictionaryValue* manifest_value() const {
- return static_data_->manifest_value.get();
- }
-
- const std::string default_locale() const {
- return static_data_->default_locale;
- }
-
- // Chrome URL overrides (see ExtensionOverrideUI).
- const URLOverrideMap& GetChromeURLOverrides() const {
- return static_data_->chrome_url_overrides;
- }
-
- const std::string omnibox_keyword() const {
- return static_data_->omnibox_keyword;
- }
-
- bool is_app() const { return static_data_->is_app; }
- const ExtensionExtent& web_extent() const {
- return static_data_->extent;
- }
- const std::string& launch_local_path() const {
- return static_data_->launch_local_path;
- }
- const std::string& launch_web_url() const {
- return static_data_->launch_web_url;
- }
- extension_misc::LaunchContainer launch_container() const {
- return static_data_->launch_container;
- }
- int launch_width() const { return static_data_->launch_width; }
- int launch_height() const { return static_data_->launch_height; }
- bool incognito_split_mode() const {
- return static_data_->incognito_split_mode;
- }
+ ExtensionResource GetIconResource(
+ int size, ExtensionIconSet::MatchType match_type) const;
+ GURL GetIconURL(int size, ExtensionIconSet::MatchType match_type) const;
// Gets the fully resolved absolute launch URL.
GURL GetFullLaunchURL() const;
-
- // Whether the background page, if any, is ready. We don't load other
- // components until then. If there is no background page, we consider it to
- // be ready.
- bool GetBackgroundPageReady();
- void SetBackgroundPageReady();
-
- // Getter and setter for the flag that specifies whether the extension is
- // being upgraded.
- bool being_upgraded() const { return GetRuntimeData()->being_upgraded; }
- void set_being_upgraded(bool value) {
- GetRuntimeData()->being_upgraded = value;
- }
-
// Image cache related methods. These are only valid on the UI thread and
// not maintained by this class. See ImageLoadingTracker for usage. The
// |original_size| parameter should be the size of the image at |source|
// before any scaling may have been done to produce the pixels in |image|.
void SetCachedImage(const ExtensionResource& source,
const SkBitmap& image,
- const gfx::Size& original_size);
+ const gfx::Size& original_size) const;
bool HasCachedImage(const ExtensionResource& source,
- const gfx::Size& max_size);
+ const gfx::Size& max_size) const;
SkBitmap GetCachedImage(const ExtensionResource& source,
- const gfx::Size& max_size);
- bool is_hosted_app() const { return is_app() && !web_extent().is_empty(); }
- bool is_packaged_app() const { return is_app() && web_extent().is_empty(); }
-
+ const gfx::Size& max_size) const;
// Returns true if this extension is a COMPONENT extension, or if it is
// on the whitelist of extensions that can script all pages.
bool CanExecuteScriptEverywhere() const;
+ // Accessors:
+
+ const FilePath& path() const { return path_; }
+ const GURL& url() const { return extension_url_; }
+ Location location() const { return location_; }
+ const std::string& id() const { return id_; }
+ const Version* version() const { return version_.get(); }
+ const std::string VersionString() const;
+ const std::string& name() const { return name_; }
+ const std::string& public_key() const { return public_key_; }
+ const std::string& description() const { return description_; }
+ bool converted_from_user_script() const {
+ return converted_from_user_script_;
+ }
+ const UserScriptList& content_scripts() const { return content_scripts_; }
+ ExtensionAction* page_action() const { return page_action_.get(); }
+ ExtensionAction* browser_action() const { return browser_action_.get(); }
+ const std::vector<PluginInfo>& plugins() const { return plugins_; }
+ const GURL& background_url() const { return background_url_; }
+ const GURL& options_url() const { return options_url_; }
+ const GURL& devtools_url() const { return devtools_url_; }
+ const std::vector<GURL>& toolstrips() const { return toolstrips_; }
+ const std::set<std::string>& api_permissions() const {
+ return api_permissions_;
+ }
+ const URLPatternList& host_permissions() const { return host_permissions_; }
+ const GURL& update_url() const { return update_url_; }
+ const ExtensionIconSet& icons() const { return icons_; }
+ const DictionaryValue* manifest_value() const {
+ return manifest_value_.get();
+ }
+ const std::string default_locale() const { return default_locale_; }
+ const URLOverrideMap& GetChromeURLOverrides() const {
+ return chrome_url_overrides_;
+ }
+ const std::string omnibox_keyword() const { return omnibox_keyword_; }
+ bool incognito_split_mode() const { return incognito_split_mode_; }
+
+ // App-related.
+ bool is_app() const { return is_app_; }
+ bool is_hosted_app() const { return is_app() && !web_extent().is_empty(); }
+ bool is_packaged_app() const { return is_app() && web_extent().is_empty(); }
+ const ExtensionExtent& web_extent() const { return extent_; }
+ const std::string& launch_local_path() const { return launch_local_path_; }
+ const std::string& launch_web_url() const { return launch_web_url_; }
+ extension_misc::LaunchContainer launch_container() const {
+ return launch_container_;
+ }
+ int launch_width() const { return launch_width_; }
+ int launch_height() const { return launch_height_; }
+
+ // Theme-related.
+ bool is_theme() const { return is_theme_; }
+ DictionaryValue* GetThemeImages() const { return theme_images_.get(); }
+ DictionaryValue* GetThemeColors() const {return theme_colors_.get(); }
+ DictionaryValue* GetThemeTints() const { return theme_tints_.get(); }
+ DictionaryValue* GetThemeDisplayProperties() const {
+ return theme_display_properties_.get();
+ }
+
private:
+ friend class base::RefCountedThreadSafe<Extension>;
+
+ // We keep a cache of images loaded from extension resources based on their
+ // path and a string representation of a size that may have been used to
+ // scale it (or the empty string if the image is at its original size).
+ typedef std::pair<FilePath, std::string> ImageCacheKey;
+ typedef std::map<ImageCacheKey, SkBitmap> ImageCache;
+
// Normalize the path for use by the extension. On Windows, this will make
// sure the drive letter is uppercase.
static FilePath MaybeNormalizePath(const FilePath& path);
+ Extension(const FilePath& path, Location location);
+ ~Extension();
+
+ // Initialize the extension from a parsed manifest.
+ // Usually, the id of an extension is generated by the "key" property of
+ // its manifest, but if |require_key| is |false|, a temporary ID will be
+ // generated based on the path.
+ bool InitFromValue(const DictionaryValue& value, bool require_key,
+ std::string* error);
+
// Helper function for implementing HasCachedImage/GetCachedImage. A return
// value of NULL means there is no matching image cached (we allow caching an
// empty SkBitmap).
SkBitmap* GetCachedImageImpl(const ExtensionResource& source,
- const gfx::Size& max_size);
+ const gfx::Size& max_size) const;
// Helper method that loads a UserScript object from a
// dictionary in the content_script list of the manifest.
@@ -691,43 +485,171 @@ class Extension {
// Figures out if a source contains keys not associated with themes - we
// don't want to allow scripts and such to be bundled with themes.
- bool ContainsNonThemeKeys(const DictionaryValue& source);
+ bool ContainsNonThemeKeys(const DictionaryValue& source) const;
// Returns true if the string is one of the known api permissions (see
// kPermissions).
- bool IsAPIPermission(const std::string& permission);
+ bool IsAPIPermission(const std::string& permission) const;
// The set of unique API install messages that the extension has.
// NOTE: This only includes messages related to permissions declared in the
// "permissions" key in the manifest. Permissions implied from other features
// of the manifest, like plugins and content scripts are not included.
- std::set<string16> GetSimplePermissionMessages();
+ std::set<string16> GetSimplePermissionMessages() const;
// The permission message displayed related to the host permissions for
// this extension.
- string16 GetHostPermissionMessage();
+ string16 GetHostPermissionMessage() const;
+
+ // Cached images for this extension. This should only be touched on the UI
+ // thread.
+ mutable ImageCache image_cache_;
+
+ // A persistent, globally unique ID. An extension's ID is used in things
+ // like directory structures and URLs, and is expected to not change across
+ // versions. It is generated as a SHA-256 hash of the extension's public
+ // key, or as a hash of the path in the case of unpacked extensions.
+ std::string id_;
+
+ // The extension's human-readable name. Name is used for display purpose. It
+ // might be wrapped with unicode bidi control characters so that it is
+ // displayed correctly in RTL context.
+ // NOTE: Name is UTF-8 and may contain non-ascii characters.
+ std::string name_;
+
+ // The absolute path to the directory the extension is stored in.
+ FilePath path_;
+
+ // Default locale for fall back. Can be empty if extension is not localized.
+ std::string default_locale_;
+
+ // If true, a separate process will be used for the extension in incognito
+ // mode.
+ bool incognito_split_mode_;
+
+ // Defines the set of URLs in the extension's web content.
+ ExtensionExtent extent_;
+
+ // The set of host permissions that the extension effectively has access to,
+ // which is a merge of host_permissions_ and all of the match patterns in
+ // any content scripts the extension has. This is used to determine which
+ // URLs have the ability to load an extension's resources via embedded
+ // chrome-extension: URLs (see extension_protocols.cc).
+ ExtensionExtent effective_host_permissions_;
+
+ // The set of module-level APIs this extension can use.
+ std::set<std::string> api_permissions_;
+
+ // The icons for the extension.
+ ExtensionIconSet icons_;
+
+ // The base extension url for the extension.
+ GURL extension_url_;
+
+ // The location the extension was loaded from.
+ Location location_;
+
+ // The extension's version.
+ scoped_ptr<Version> version_;
+
+ // An optional longer description of the extension.
+ std::string description_;
+
+ // True if the extension was generated from a user script. (We show slightly
+ // different UI if so).
+ bool converted_from_user_script_;
+
+ // Paths to the content scripts the extension contains.
+ UserScriptList content_scripts_;
+
+ // The extension's page action, if any.
+ scoped_ptr<ExtensionAction> page_action_;
+
+ // The extension's browser action, if any.
+ scoped_ptr<ExtensionAction> browser_action_;
+
+ // Optional list of NPAPI plugins and associated properties.
+ std::vector<PluginInfo> plugins_;
+
+ // Optional URL to a master page of which a single instance should be always
+ // loaded in the background.
+ GURL background_url_;
+
+ // Optional URL to a page for setting options/preferences.
+ GURL options_url_;
+
+ // Optional URL to a devtools extension page.
+ GURL devtools_url_;
+
+ // Optional list of toolstrips and associated properties.
+ std::vector<GURL> toolstrips_;
+
+ // The public key used to sign the contents of the crx package.
+ std::string public_key_;
+
+ // A map of resource id's to relative file paths.
+ scoped_ptr<DictionaryValue> theme_images_;
+
+ // A map of color names to colors.
+ scoped_ptr<DictionaryValue> theme_colors_;
+
+ // A map of color names to colors.
+ scoped_ptr<DictionaryValue> theme_tints_;
+
+ // A map of display properties.
+ scoped_ptr<DictionaryValue> theme_display_properties_;
+
+ // Whether the extension is a theme.
+ bool is_theme_;
+
+ // The sites this extension has permission to talk to (using XHR, etc).
+ URLPatternList host_permissions_;
+
+ // The homepage for this extension. Useful if it is not hosted by Google and
+ // therefore does not have a Gallery URL.
+ GURL homepage_url_;
+
+ // URL for fetching an update manifest
+ GURL update_url_;
+
+ // A copy of the manifest that this extension was created from.
+ scoped_ptr<DictionaryValue> manifest_value_;
+
+ // A map of chrome:// hostnames (newtab, downloads, etc.) to Extension URLs
+ // which override the handling of those URLs. (see ExtensionOverrideUI).
+ URLOverrideMap chrome_url_overrides_;
+
+ // Whether this extension uses app features.
+ bool is_app_;
+
+ // The local path inside the extension to use with the launcher.
+ std::string launch_local_path_;
+
+ // A web url to use with the launcher. Note that this might be relative or
+ // absolute. If relative, it is relative to web_origin.
+ std::string launch_web_url_;
- // Returns a mutable pointer to our runtime data. Can only be called on
- // the UI thread.
- RuntimeData* GetRuntimeData() const;
+ // The type of container to launch into.
+ extension_misc::LaunchContainer launch_container_;
- // Collection of extension data that doesn't change doesn't change once an
- // Extension object has been initialized. The mutable version is valid only
- // until InitFromValue finishes, to ensure we don't accidentally modify it
- // post-initialization.
- StaticData* mutable_static_data_;
- scoped_refptr<const StaticData> static_data_;
+ // The default size of the container when launching. Only respected for
+ // containers like panels and windows.
+ int launch_width_;
+ int launch_height_;
- // Runtime data.
- scoped_ptr<const RuntimeData> runtime_data_;
+ // The Omnibox keyword for this extension, or empty if there is none.
+ std::string omnibox_keyword_;
FRIEND_TEST_ALL_PREFIXES(ExtensionTest, LoadPageActionHelper);
+ FRIEND_TEST_ALL_PREFIXES(ExtensionTest, InitFromValueInvalid);
+ FRIEND_TEST_ALL_PREFIXES(ExtensionTest, InitFromValueValid);
+ FRIEND_TEST_ALL_PREFIXES(ExtensionTest, InitFromValueValidNameInRTL);
FRIEND_TEST_ALL_PREFIXES(TabStripModelTest, Apps);
DISALLOW_COPY_AND_ASSIGN(Extension);
};
-typedef std::vector<Extension*> ExtensionList;
+typedef std::vector< scoped_refptr<const Extension> > ExtensionList;
typedef std::set<std::string> ExtensionIdSet;
// Handy struct to pass core extension info around.
diff --git a/chrome/common/extensions/extension_action.h b/chrome/common/extensions/extension_action.h
index a50ebf3..a1e5bc4 100644
--- a/chrome/common/extensions/extension_action.h
+++ b/chrome/common/extensions/extension_action.h
@@ -151,7 +151,7 @@ class ExtensionAction {
};
template<class T>
- void SetValue(std::map<int, T>* map, int tab_id, T val) {
+ void SetValue(std::map<int, T>* map, int tab_id, const T& val) {
(*map)[tab_id] = val;
}
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index 983fda4..5e418b5 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -19,6 +19,7 @@ const char* kDefaultLocale = "default_locale";
const char* kDescription = "description";
const char* kDevToolsPage = "devtools_page";
const char* kExcludeGlobs = "exclude_globs";
+const char* kHomepageURL = "homepage_url";
const char* kIcons = "icons";
const char* kIncognito = "incognito";
const char* kIncludeGlobs = "include_globs";
@@ -124,6 +125,8 @@ const char* kInvalidGlob =
"Invalid value for 'content_scripts[*].*[*]'.";
const char* kInvalidGlobList =
"Invalid value for 'content_scripts[*].*'.";
+const char* kInvalidHomepageURL =
+ "Invalid value for homepage url: '[*]'.";
const char* kInvalidIconPath =
"Invalid value for 'icons[\"*\"]'.";
const char* kInvalidIcons =
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index e76ce24..332f386 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -24,6 +24,7 @@ namespace extension_manifest_keys {
extern const char* kDescription;
extern const char* kDevToolsPage;
extern const char* kExcludeGlobs;
+ extern const char* kHomepageURL;
extern const char* kIcons;
extern const char* kIncognito;
extern const char* kIncludeGlobs;
@@ -108,6 +109,7 @@ namespace extension_manifest_errors {
extern const char* kInvalidDevToolsPage;
extern const char* kInvalidGlob;
extern const char* kInvalidGlobList;
+ extern const char* kInvalidHomepageURL;
extern const char* kInvalidIconPath;
extern const char* kInvalidIcons;
extern const char* kInvalidIncognitoBehavior;
diff --git a/chrome/common/extensions/extension_file_util.cc b/chrome/common/extensions/extension_file_util.cc
index d530357..f2350cc 100644
--- a/chrome/common/extensions/extension_file_util.cc
+++ b/chrome/common/extensions/extension_file_util.cc
@@ -54,7 +54,7 @@ FilePath InstallExtension(const FilePath& unpacked_source_dir,
const int kMaxAttempts = 100;
for (int i = 0; i < kMaxAttempts; ++i) {
FilePath candidate = extension_dir.AppendASCII(
- StringPrintf("%s_%u", version.c_str(), i));
+ base::StringPrintf("%s_%u", version.c_str(), i));
if (!file_util::PathExists(candidate)) {
version_dir = candidate;
break;
@@ -81,15 +81,14 @@ void UninstallExtension(const FilePath& extensions_dir,
file_util::Delete(extensions_dir.AppendASCII(id), true); // recursive.
}
-Extension* LoadExtension(const FilePath& extension_path,
- Extension::Location location,
- bool require_key,
- std::string* error) {
+scoped_refptr<Extension> LoadExtension(const FilePath& extension_path,
+ Extension::Location location,
+ bool require_key,
+ std::string* error) {
FilePath manifest_path =
extension_path.Append(Extension::kManifestFilename);
if (!file_util::PathExists(manifest_path)) {
- *error =
- l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE);
+ *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE);
return NULL;
}
@@ -101,37 +100,33 @@ Extension* LoadExtension(const FilePath& extension_path,
// It would be cleaner to have the JSON reader give a specific error
// in this case, but other code tests for a file error with
// error->empty(). For now, be consistent.
- *error =
- l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE);
+ *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE);
} else {
- *error = StringPrintf("%s %s",
- errors::kManifestParseError,
- error->c_str());
+ *error = base::StringPrintf("%s %s",
+ errors::kManifestParseError,
+ error->c_str());
}
return NULL;
}
if (!root->IsType(Value::TYPE_DICTIONARY)) {
- *error =
- l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_INVALID);
+ *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_INVALID);
return NULL;
}
DictionaryValue* manifest = static_cast<DictionaryValue*>(root.get());
-
- scoped_ptr<Extension> extension(new Extension(extension_path));
- extension->set_location(location);
-
- if (!extension_l10n_util::LocalizeExtension(extension.get(), manifest, error))
+ if (!extension_l10n_util::LocalizeExtension(extension_path, manifest, error))
return NULL;
- if (!extension->InitFromValue(*manifest, require_key, error))
+ scoped_refptr<Extension> extension(Extension::Create(
+ extension_path, location, *manifest, require_key, error));
+ if (!extension.get())
return NULL;
if (!ValidateExtension(extension.get(), error))
return NULL;
- return extension.release();
+ return extension;
}
bool ValidateExtension(Extension* extension, std::string* error) {
@@ -411,7 +406,7 @@ static bool ValidateLocaleInfo(const Extension& extension, std::string* error) {
locale_path.Append(Extension::kMessagesFilename);
if (!file_util::PathExists(messages_path)) {
- *error = StringPrintf(
+ *error = base::StringPrintf(
"%s %s", errors::kLocalesMessagesFileMissing,
WideToUTF8(messages_path.ToWStringHack()).c_str());
return false;
@@ -480,10 +475,10 @@ bool CheckForIllegalFilenames(const FilePath& extension_path,
if (filename.find_first_of(FILE_PATH_LITERAL("_")) != 0) continue;
if (reserved_underscore_names.find(filename) ==
reserved_underscore_names.end()) {
- *error = StringPrintf(
- "Cannot load extension with file or directory name %s. "
- "Filenames starting with \"_\" are reserved for use by the system.",
- filename.c_str());
+ *error = base::StringPrintf(
+ "Cannot load extension with file or directory name %s. "
+ "Filenames starting with \"_\" are reserved for use by the system.",
+ filename.c_str());
return false;
}
}
diff --git a/chrome/common/extensions/extension_file_util.h b/chrome/common/extensions/extension_file_util.h
index 1b8fb76..f6a72bc 100644
--- a/chrome/common/extensions/extension_file_util.h
+++ b/chrome/common/extensions/extension_file_util.h
@@ -37,10 +37,10 @@ void UninstallExtension(const FilePath& extensions_dir,
// Loads and validates an extension from the specified directory. Returns NULL
// on failure, with a description of the error in |error|.
-Extension* LoadExtension(const FilePath& extension_root,
- Extension::Location location,
- bool require_key,
- std::string* error);
+scoped_refptr<Extension> LoadExtension(const FilePath& extension_root,
+ Extension::Location location,
+ bool require_key,
+ std::string* error);
// Returns true if the given extension object is valid and consistent.
// Otherwise, a description of the error is returned in |error|.
diff --git a/chrome/common/extensions/extension_file_util_unittest.cc b/chrome/common/extensions/extension_file_util_unittest.cc
index 634df05..230712d 100644
--- a/chrome/common/extensions/extension_file_util_unittest.cc
+++ b/chrome/common/extensions/extension_file_util_unittest.cc
@@ -78,7 +78,7 @@ TEST(ExtensionFileUtil, LoadExtensionWithValidLocales) {
.AppendASCII("1.0.0.0");
std::string error;
- scoped_ptr<Extension> extension(extension_file_util::LoadExtension(
+ scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
install_dir, Extension::LOAD, false, &error));
ASSERT_TRUE(extension != NULL);
EXPECT_EQ("The first extension that I made.", extension->description());
@@ -94,7 +94,7 @@ TEST(ExtensionFileUtil, LoadExtensionWithoutLocalesFolder) {
.AppendASCII("1.0");
std::string error;
- scoped_ptr<Extension> extension(extension_file_util::LoadExtension(
+ scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
install_dir, Extension::LOAD, false, &error));
ASSERT_FALSE(extension == NULL);
EXPECT_TRUE(error.empty());
@@ -152,7 +152,7 @@ TEST(ExtensionFileUtil, LoadExtensionGivesHelpfullErrorOnMissingManifest) {
.AppendASCII("1.0");
std::string error;
- scoped_ptr<Extension> extension(extension_file_util::LoadExtension(
+ scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
install_dir, Extension::LOAD, false, &error));
ASSERT_TRUE(extension == NULL);
ASSERT_FALSE(error.empty());
@@ -169,7 +169,7 @@ TEST(ExtensionFileUtil, LoadExtensionGivesHelpfullErrorOnBadManifest) {
.AppendASCII("1.0");
std::string error;
- scoped_ptr<Extension> extension(extension_file_util::LoadExtension(
+ scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
install_dir, Extension::LOAD, false, &error));
ASSERT_TRUE(extension == NULL);
ASSERT_FALSE(error.empty());
@@ -185,7 +185,7 @@ TEST(ExtensionFileUtil, FailLoadingNonUTF8Scripts) {
.AppendASCII("bad_encoding");
std::string error;
- scoped_ptr<Extension> extension(extension_file_util::LoadExtension(
+ scoped_refptr<Extension> extension(extension_file_util::LoadExtension(
install_dir, Extension::LOAD, false, &error));
ASSERT_TRUE(extension == NULL);
ASSERT_STREQ("Could not load file 'bad_encoding.js' for content script. "
diff --git a/chrome/common/extensions/extension_l10n_util.cc b/chrome/common/extensions/extension_l10n_util.cc
index 4187689..8c7826c 100644
--- a/chrome/common/extensions/extension_l10n_util.cc
+++ b/chrome/common/extensions/extension_l10n_util.cc
@@ -113,7 +113,7 @@ bool LocalizeManifest(const ExtensionMessageBundle& messages,
return true;
}
-bool LocalizeExtension(Extension* extension,
+bool LocalizeExtension(const FilePath& extension_path,
DictionaryValue* manifest,
std::string* error) {
DCHECK(manifest);
@@ -122,7 +122,7 @@ bool LocalizeExtension(Extension* extension,
scoped_ptr<ExtensionMessageBundle> message_bundle(
extension_file_util::LoadExtensionMessageBundle(
- extension->path(), default_locale, error));
+ extension_path, default_locale, error));
if (!message_bundle.get() && !error->empty())
return false;
@@ -146,8 +146,8 @@ bool AddLocale(const std::set<std::string>& chrome_locales,
if (chrome_locales.find(locale_name) == chrome_locales.end()) {
// Warn if there is an extension locale that's not in the Chrome list,
// but don't fail.
- LOG(WARNING) << StringPrintf("Supplied locale %s is not supported.",
- locale_name.c_str());
+ LOG(WARNING) << base::StringPrintf("Supplied locale %s is not supported.",
+ locale_name.c_str());
return true;
}
// Check if messages file is actually present (but don't check content).
@@ -155,8 +155,8 @@ bool AddLocale(const std::set<std::string>& chrome_locales,
locale_folder.Append(Extension::kMessagesFilename))) {
valid_locales->insert(locale_name);
} else {
- *error = StringPrintf("Catalog file is missing for locale %s.",
- locale_name.c_str());
+ *error = base::StringPrintf("Catalog file is missing for locale %s.",
+ locale_name.c_str());
return false;
}
@@ -250,8 +250,8 @@ static DictionaryValue* LoadMessageFile(const FilePath& locale_path,
if (!dictionary && error->empty()) {
// JSONFileValueSerializer just returns NULL if file cannot be found. It
// doesn't set the error, so we have to do it.
- *error = StringPrintf("Catalog file is missing for locale %s.",
- extension_locale.c_str());
+ *error = base::StringPrintf("Catalog file is missing for locale %s.",
+ extension_locale.c_str());
}
return static_cast<DictionaryValue*>(dictionary);
diff --git a/chrome/common/extensions/extension_l10n_util.h b/chrome/common/extensions/extension_l10n_util.h
index 48dc901..e1fdfa0 100644
--- a/chrome/common/extensions/extension_l10n_util.h
+++ b/chrome/common/extensions/extension_l10n_util.h
@@ -44,7 +44,7 @@ bool LocalizeManifest(const ExtensionMessageBundle& messages,
// Load message catalogs, localize manifest and attach message bundle to the
// extension.
-bool LocalizeExtension(Extension* extension,
+bool LocalizeExtension(const FilePath& extension_path,
DictionaryValue* manifest,
std::string* error);
diff --git a/chrome/common/extensions/extension_localization_peer.cc b/chrome/common/extensions/extension_localization_peer.cc
index 06e0317..e04bd0b 100644
--- a/chrome/common/extensions/extension_localization_peer.cc
+++ b/chrome/common/extensions/extension_localization_peer.cc
@@ -90,10 +90,6 @@ void ExtensionLocalizationPeer::OnCompletedRequest(
original_peer_->OnCompletedRequest(status, security_info, completion_time);
}
-GURL ExtensionLocalizationPeer::GetURLForDebugging() const {
- return original_peer_->GetURLForDebugging();
-}
-
void ExtensionLocalizationPeer::ReplaceMessages() {
if (!message_sender_ || data_.empty())
return;
diff --git a/chrome/common/extensions/extension_localization_peer.h b/chrome/common/extensions/extension_localization_peer.h
index b2b7c7a..1274421 100644
--- a/chrome/common/extensions/extension_localization_peer.h
+++ b/chrome/common/extensions/extension_localization_peer.h
@@ -45,7 +45,6 @@ class ExtensionLocalizationPeer
virtual void OnCompletedRequest(const URLRequestStatus& status,
const std::string& security_info,
const base::Time& completion_time);
- virtual GURL GetURLForDebugging() const;
private:
friend class ExtensionLocalizationPeerTest;
diff --git a/chrome/common/extensions/extension_localization_peer_unittest.cc b/chrome/common/extensions/extension_localization_peer_unittest.cc
index bc6f73f..dc67d5b 100644
--- a/chrome/common/extensions/extension_localization_peer_unittest.cc
+++ b/chrome/common/extensions/extension_localization_peer_unittest.cc
@@ -72,7 +72,6 @@ class MockResourceLoaderBridgePeer
const URLRequestStatus& status,
const std::string& security_info,
const base::Time& completion_time));
- MOCK_CONST_METHOD0(GetURLForDebugging, GURL());
private:
DISALLOW_COPY_AND_ASSIGN(MockResourceLoaderBridgePeer);
@@ -153,7 +152,6 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestEmptyData) {
// It will self-delete once it exits OnCompletedRequest.
ExtensionLocalizationPeer* filter_peer = filter_peer_.release();
- EXPECT_CALL(*original_peer_, GetURLForDebugging()).Times(0);
EXPECT_CALL(*original_peer_, OnReceivedData(_, _)).Times(0);
EXPECT_CALL(*sender_, Send(_)).Times(0);
@@ -172,7 +170,6 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestNoCatalogs) {
SetData(filter_peer, "some text");
- EXPECT_CALL(*original_peer_, GetURLForDebugging()).Times(0);
EXPECT_CALL(*sender_, Send(_));
std::string data = GetData(filter_peer);
@@ -208,7 +205,6 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestWithCatalogs) {
SetData(filter_peer, "some __MSG_text__");
- EXPECT_CALL(*original_peer_, GetURLForDebugging()).Times(0);
// We already have messages in memory, Send will be skipped.
EXPECT_CALL(*sender_, Send(_)).Times(0);
@@ -240,7 +236,6 @@ TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestReplaceMessagesFails) {
std::string message("some __MSG_missing_message__");
SetData(filter_peer, message);
- EXPECT_CALL(*original_peer_, GetURLForDebugging()).Times(0);
// We already have messages in memory, Send will be skipped.
EXPECT_CALL(*sender_, Send(_)).Times(0);
diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc
index ac56f70..3a89166 100644
--- a/chrome/common/extensions/extension_manifests_unittest.cc
+++ b/chrome/common/extensions/extension_manifests_unittest.cc
@@ -37,53 +37,48 @@ class ExtensionManifestTest : public testing::Test {
return static_cast<DictionaryValue*>(serializer.Deserialize(NULL, error));
}
- Extension* LoadExtensionWithLocation(DictionaryValue* value,
- Extension::Location location,
- std::string* error) {
+ scoped_refptr<Extension> LoadExtensionWithLocation(
+ DictionaryValue* value,
+ Extension::Location location,
+ std::string* error) {
FilePath path;
PathService::Get(chrome::DIR_TEST_DATA, &path);
path = path.AppendASCII("extensions").AppendASCII("manifest_tests");
-
- scoped_ptr<Extension> extension(new Extension(path.DirName()));
- extension->set_location(location);
-
- if (!extension->InitFromValue(*value, false, error))
- return NULL;
-
- return extension.release();
+ return Extension::Create(path.DirName(), location, *value, false, error);
}
- Extension* LoadExtension(const std::string& name,
- std::string* error) {
+ scoped_refptr<Extension> LoadExtension(const std::string& name,
+ std::string* error) {
return LoadExtensionWithLocation(name, Extension::INTERNAL, error);
}
- Extension* LoadExtension(DictionaryValue* value,
- std::string* error) {
+ scoped_refptr<Extension> LoadExtension(DictionaryValue* value,
+ std::string* error) {
return LoadExtensionWithLocation(value, Extension::INTERNAL, error);
}
- Extension* LoadExtensionWithLocation(const std::string& name,
- Extension::Location location,
- std::string* error) {
+ scoped_refptr<Extension> LoadExtensionWithLocation(
+ const std::string& name,
+ Extension::Location location,
+ std::string* error) {
scoped_ptr<DictionaryValue> value(LoadManifestFile(name, error));
if (!value.get())
return NULL;
return LoadExtensionWithLocation(value.get(), location, error);
}
- Extension* LoadAndExpectSuccess(const std::string& name) {
+ scoped_refptr<Extension> LoadAndExpectSuccess(const std::string& name) {
std::string error;
- Extension* extension = LoadExtension(name, &error);
+ scoped_refptr<Extension> extension = LoadExtension(name, &error);
EXPECT_TRUE(extension) << name;
EXPECT_EQ("", error) << name;
return extension;
}
- Extension* LoadAndExpectSuccess(DictionaryValue* manifest,
- const std::string& name) {
+ scoped_refptr<Extension> LoadAndExpectSuccess(DictionaryValue* manifest,
+ const std::string& name) {
std::string error;
- Extension* extension = LoadExtension(manifest, &error);
+ scoped_refptr<Extension> extension = LoadExtension(manifest, &error);
EXPECT_TRUE(extension) << "Unexpected success for " << name;
EXPECT_EQ("", error) << "Unexpected no error for " << name;
return extension;
@@ -103,7 +98,7 @@ class ExtensionManifestTest : public testing::Test {
void LoadAndExpectError(const std::string& name,
const std::string& expected_error) {
std::string error;
- scoped_ptr<Extension> extension(LoadExtension(name, &error));
+ scoped_refptr<Extension> extension(LoadExtension(name, &error));
VerifyExpectedError(extension.get(), name, error, expected_error);
}
@@ -111,7 +106,7 @@ class ExtensionManifestTest : public testing::Test {
const std::string& name,
const std::string& expected_error) {
std::string error;
- scoped_ptr<Extension> extension(LoadExtension(manifest, &error));
+ scoped_refptr<Extension> extension(LoadExtension(manifest, &error));
VerifyExpectedError(extension.get(), name, error, expected_error);
}
@@ -119,7 +114,7 @@ class ExtensionManifestTest : public testing::Test {
};
TEST_F(ExtensionManifestTest, ValidApp) {
- scoped_ptr<Extension> extension(LoadAndExpectSuccess("valid_app.json"));
+ scoped_refptr<Extension> extension(LoadAndExpectSuccess("valid_app.json"));
ASSERT_EQ(2u, extension->web_extent().patterns().size());
EXPECT_EQ("http://www.google.com/mail/*",
extension->web_extent().patterns()[0].GetAsString());
@@ -145,7 +140,7 @@ TEST_F(ExtensionManifestTest, AppWebUrls) {
ExtensionErrorUtils::FormatErrorMessage(
errors::kInvalidWebURL, "0"));
- scoped_ptr<Extension> extension(
+ scoped_refptr<Extension> extension(
LoadAndExpectSuccess("web_urls_default.json"));
ASSERT_EQ(1u, extension->web_extent().patterns().size());
EXPECT_EQ("*://www.google.com/*",
@@ -153,21 +148,21 @@ TEST_F(ExtensionManifestTest, AppWebUrls) {
}
TEST_F(ExtensionManifestTest, AppLaunchContainer) {
- scoped_ptr<Extension> extension;
+ scoped_refptr<Extension> extension;
- extension.reset(LoadAndExpectSuccess("launch_tab.json"));
+ extension = LoadAndExpectSuccess("launch_tab.json");
EXPECT_EQ(extension_misc::LAUNCH_TAB, extension->launch_container());
- extension.reset(LoadAndExpectSuccess("launch_panel.json"));
+ extension = LoadAndExpectSuccess("launch_panel.json");
EXPECT_EQ(extension_misc::LAUNCH_PANEL, extension->launch_container());
- extension.reset(LoadAndExpectSuccess("launch_default.json"));
+ extension = LoadAndExpectSuccess("launch_default.json");
EXPECT_EQ(extension_misc::LAUNCH_TAB, extension->launch_container());
- extension.reset(LoadAndExpectSuccess("launch_width.json"));
+ extension = LoadAndExpectSuccess("launch_width.json");
EXPECT_EQ(640, extension->launch_width());
- extension.reset(LoadAndExpectSuccess("launch_height.json"));
+ extension = LoadAndExpectSuccess("launch_height.json");
EXPECT_EQ(480, extension->launch_height());
LoadAndExpectError("launch_window.json",
@@ -198,15 +193,15 @@ TEST_F(ExtensionManifestTest, AppLaunchURL) {
LoadAndExpectError("launch_url_invalid_type.json",
errors::kInvalidLaunchWebURL);
- scoped_ptr<Extension> extension;
- extension.reset(LoadAndExpectSuccess("launch_local_path.json"));
+ scoped_refptr<Extension> extension;
+ extension = LoadAndExpectSuccess("launch_local_path.json");
EXPECT_EQ(extension->url().spec() + "launch.html",
extension->GetFullLaunchURL().spec());
LoadAndExpectError("launch_web_url_relative.json",
errors::kInvalidLaunchWebURL);
- extension.reset(LoadAndExpectSuccess("launch_web_url_absolute.json"));
+ extension = LoadAndExpectSuccess("launch_web_url_absolute.json");
EXPECT_EQ(GURL("http://www.google.com/launch.html"),
extension->GetFullLaunchURL());
}
@@ -217,13 +212,13 @@ TEST_F(ExtensionManifestTest, Override) {
LoadAndExpectError("override_invalid_page.json",
errors::kInvalidChromeURLOverrides);
- scoped_ptr<Extension> extension;
+ scoped_refptr<Extension> extension;
- extension.reset(LoadAndExpectSuccess("override_new_tab.json"));
+ extension = LoadAndExpectSuccess("override_new_tab.json");
EXPECT_EQ(extension->url().spec() + "newtab.html",
extension->GetChromeURLOverrides().find("newtab")->second.spec());
- extension.reset(LoadAndExpectSuccess("override_history.json"));
+ extension = LoadAndExpectSuccess("override_history.json");
EXPECT_EQ(extension->url().spec() + "history.html",
extension->GetChromeURLOverrides().find("history")->second.spec());
}
@@ -237,11 +232,11 @@ TEST_F(ExtensionManifestTest, ChromeResourcesPermissionValidOnlyForComponents) {
LoadAndExpectError("permission_chrome_resources_url.json",
errors::kInvalidPermissionScheme);
std::string error;
- scoped_ptr<Extension> extension;
- extension.reset(LoadExtensionWithLocation(
+ scoped_refptr<Extension> extension;
+ extension = LoadExtensionWithLocation(
"permission_chrome_resources_url.json",
Extension::COMPONENT,
- &error));
+ &error);
EXPECT_EQ("", error);
}
@@ -260,8 +255,8 @@ TEST_F(ExtensionManifestTest, DevToolsExtensions) {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableExperimentalExtensionApis);
- scoped_ptr<Extension> extension;
- extension.reset(LoadAndExpectSuccess("devtools_extension.json"));
+ scoped_refptr<Extension> extension;
+ extension = LoadAndExpectSuccess("devtools_extension.json");
EXPECT_EQ(extension->url().spec() + "devtools.html",
extension->devtools_url().spec());
*CommandLine::ForCurrentProcess() = old_command_line;
@@ -275,11 +270,10 @@ TEST_F(ExtensionManifestTest, DisallowHybridApps) {
}
TEST_F(ExtensionManifestTest, OptionsPageInApps) {
- scoped_ptr<Extension> extension;
+ scoped_refptr<Extension> extension;
// Allow options page with absolute URL in hosed apps.
- extension.reset(
- LoadAndExpectSuccess("hosted_app_absolute_options.json"));
+ extension = LoadAndExpectSuccess("hosted_app_absolute_options.json");
EXPECT_STREQ("http",
extension->options_url().scheme().c_str());
EXPECT_STREQ("example.com",
@@ -313,10 +307,10 @@ TEST_F(ExtensionManifestTest, DisallowExtensionPermissions) {
StringValue* p = new StringValue(name);
permissions->Clear();
permissions->Append(p);
- std::string message_name = StringPrintf("permission-%s", name);
+ std::string message_name = base::StringPrintf("permission-%s", name);
if (Extension::IsHostedAppPermission(name)) {
- scoped_ptr<Extension> extension;
- extension.reset(LoadAndExpectSuccess(manifest.get(), message_name));
+ scoped_refptr<Extension> extension;
+ extension = LoadAndExpectSuccess(manifest.get(), message_name);
} else {
LoadAndExpectError(manifest.get(), message_name,
errors::kInvalidPermission);
@@ -325,7 +319,7 @@ TEST_F(ExtensionManifestTest, DisallowExtensionPermissions) {
}
TEST_F(ExtensionManifestTest, NormalizeIconPaths) {
- scoped_ptr<Extension> extension(
+ scoped_refptr<Extension> extension(
LoadAndExpectSuccess("normalize_icon_paths.json"));
EXPECT_EQ("16.png",
extension->icons().Get(16, ExtensionIconSet::MATCH_EXACTLY));
@@ -338,3 +332,38 @@ TEST_F(ExtensionManifestTest, DisallowMultipleUISurfaces) {
LoadAndExpectError("multiple_ui_surfaces_2.json", errors::kOneUISurfaceOnly);
LoadAndExpectError("multiple_ui_surfaces_3.json", errors::kOneUISurfaceOnly);
}
+
+TEST_F(ExtensionManifestTest, ParseHomepageURLs) {
+ scoped_refptr<Extension> extension(
+ LoadAndExpectSuccess("homepage_valid.json"));
+ LoadAndExpectError("homepage_empty.json",
+ extension_manifest_errors::kInvalidHomepageURL);
+ LoadAndExpectError("homepage_invalid.json",
+ extension_manifest_errors::kInvalidHomepageURL);
+}
+
+TEST_F(ExtensionManifestTest, GetHomepageURL) {
+ scoped_refptr<Extension> extension(
+ LoadAndExpectSuccess("homepage_valid.json"));
+ EXPECT_EQ(GURL("http://foo.com#bar"), extension->GetHomepageURL());
+
+ // The Google Gallery URL ends with the id, which depends on the path, which
+ // can be different in testing, so we just check the part before id.
+ extension = LoadAndExpectSuccess("homepage_google_hosted.json");
+ EXPECT_TRUE(StartsWithASCII(extension->GetHomepageURL().spec(),
+ "https://chrome.google.com/extensions/detail/",
+ false));
+
+ extension = LoadAndExpectSuccess("homepage_externally_hosted.json");
+ EXPECT_EQ(GURL(), extension->GetHomepageURL());
+}
+
+TEST_F(ExtensionManifestTest, DefaultPathForExtent) {
+ scoped_refptr<Extension> extension(
+ LoadAndExpectSuccess("default_path_for_extent.json"));
+
+ ASSERT_EQ(1u, extension->web_extent().patterns().size());
+ EXPECT_EQ("/*", extension->web_extent().patterns()[0].path());
+ EXPECT_TRUE(extension->web_extent().ContainsURL(
+ GURL("http://www.google.com/monkey")));
+}
diff --git a/chrome/common/extensions/extension_message_bundle.cc b/chrome/common/extensions/extension_message_bundle.cc
index 4de6b45..3f7c152 100644
--- a/chrome/common/extensions/extension_message_bundle.cc
+++ b/chrome/common/extensions/extension_message_bundle.cc
@@ -48,8 +48,10 @@ const char* ExtensionMessageBundle::kBidiRightEdgeValue = "right";
// Formats message in case we encounter a bad formed key in the JSON object.
// Returns false and sets |error| to actual error message.
static bool BadKeyMessage(const std::string& name, std::string* error) {
- *error = StringPrintf("Name of a key \"%s\" is invalid. Only ASCII [a-z], "
- "[A-Z], [0-9] and \"_\" are allowed.", name.c_str());
+ *error = base::StringPrintf(
+ "Name of a key \"%s\" is invalid. Only ASCII [a-z], "
+ "[A-Z], [0-9] and \"_\" are allowed.",
+ name.c_str());
return false;
}
@@ -134,13 +136,13 @@ bool ExtensionMessageBundle::GetMessageValue(const std::string& key,
// Get the top level tree for given key (name part).
DictionaryValue* name_tree;
if (!catalog.GetDictionaryWithoutPathExpansion(key, &name_tree)) {
- *error = StringPrintf("Not a valid tree for key %s.", key.c_str());
+ *error = base::StringPrintf("Not a valid tree for key %s.", key.c_str());
return false;
}
// Extract message from it.
if (!name_tree->GetString(kMessageKey, value)) {
- *error = StringPrintf("There is no \"%s\" element for key %s.", kMessageKey,
- key.c_str());
+ *error = base::StringPrintf(
+ "There is no \"%s\" element for key %s.", kMessageKey, key.c_str());
return false;
}
@@ -166,8 +168,8 @@ bool ExtensionMessageBundle::GetPlaceholders(const DictionaryValue& name_tree,
DictionaryValue* placeholders_tree;
if (!name_tree.GetDictionary(kPlaceholdersKey, &placeholders_tree)) {
- *error = StringPrintf("Not a valid \"%s\" element for key %s.",
- kPlaceholdersKey, name_key.c_str());
+ *error = base::StringPrintf("Not a valid \"%s\" element for key %s.",
+ kPlaceholdersKey, name_key.c_str());
return false;
}
@@ -179,15 +181,15 @@ bool ExtensionMessageBundle::GetPlaceholders(const DictionaryValue& name_tree,
return BadKeyMessage(content_key, error);
if (!placeholders_tree->GetDictionaryWithoutPathExpansion(content_key,
&placeholder)) {
- *error = StringPrintf("Invalid placeholder %s for key %s",
- content_key.c_str(),
- name_key.c_str());
+ *error = base::StringPrintf("Invalid placeholder %s for key %s",
+ content_key.c_str(),
+ name_key.c_str());
return false;
}
std::string content;
if (!placeholder->GetString(kContentKey, &content)) {
- *error = StringPrintf("Invalid \"%s\" element for key %s.",
- kContentKey, name_key.c_str());
+ *error = base::StringPrintf("Invalid \"%s\" element for key %s.",
+ kContentKey, name_key.c_str());
return false;
}
(*placeholders)[StringToLowerASCII(content_key)] = content;
@@ -253,10 +255,10 @@ bool ExtensionMessageBundle::ReplaceVariables(
SubstitutionMap::const_iterator it =
variables.find(StringToLowerASCII(var_name));
if (it == variables.end()) {
- *error = StringPrintf("Variable %s%s%s used but not defined.",
- var_begin_delimiter.c_str(),
- var_name.c_str(),
- var_end_delimiter.c_str());
+ *error = base::StringPrintf("Variable %s%s%s used but not defined.",
+ var_begin_delimiter.c_str(),
+ var_name.c_str(),
+ var_end_delimiter.c_str());
return false;
}
diff --git a/chrome/common/extensions/extension_resource.cc b/chrome/common/extensions/extension_resource.cc
index d3c5898..be22ec9 100644
--- a/chrome/common/extensions/extension_resource.cc
+++ b/chrome/common/extensions/extension_resource.cc
@@ -6,6 +6,7 @@
#include "base/file_util.h"
#include "base/logging.h"
+#include "base/thread_restrictions.h"
PlatformThreadId ExtensionResource::file_thread_id_ = 0;
@@ -45,6 +46,12 @@ const FilePath& ExtensionResource::GetFilePath() const {
// static
FilePath ExtensionResource::GetFilePathOnAnyThreadHack(
const FilePath& extension_root, const FilePath& relative_path) {
+ // This function is a hack, and causes us to block the IO thread.
+ // Fixing
+ // http://code.google.com/p/chromium/issues/detail?id=59849
+ // would also fix this. Suppress the error for now.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
// We need to resolve the parent references in the extension_root
// path on its own because IsParent doesn't like parent references.
FilePath clean_extension_root(extension_root);
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index d2a7049..3f86bbd 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -77,7 +77,9 @@ TEST(ExtensionTest, InitFromValueInvalid) {
#elif defined(OS_POSIX)
FilePath path(FILE_PATH_LITERAL("/foo"));
#endif
- Extension extension(path);
+ scoped_refptr<Extension> extension_ptr(new Extension(path,
+ Extension::INVALID));
+ Extension& extension = *extension_ptr;
int error_code = 0;
std::string error;
@@ -303,7 +305,9 @@ TEST(ExtensionTest, InitFromValueValid) {
#elif defined(OS_POSIX)
FilePath path(FILE_PATH_LITERAL("/foo"));
#endif
- Extension extension(path);
+ scoped_refptr<Extension> extension_ptr(new Extension(path,
+ Extension::INVALID));
+ Extension& extension = *extension_ptr;
std::string error;
DictionaryValue input_value;
@@ -366,7 +370,9 @@ TEST(ExtensionTest, InitFromValueValidNameInRTL) {
#elif defined(OS_POSIX)
FilePath path(FILE_PATH_LITERAL("/foo"));
#endif
- Extension extension(path);
+ scoped_refptr<Extension> extension_ptr(new Extension(path,
+ Extension::INVALID));
+ Extension& extension = *extension_ptr;
std::string error;
DictionaryValue input_value;
@@ -403,27 +409,31 @@ TEST(ExtensionTest, GetResourceURLAndPath) {
#elif defined(OS_POSIX)
FilePath path(FILE_PATH_LITERAL("/foo"));
#endif
- Extension extension(path);
DictionaryValue input_value;
input_value.SetString(keys::kVersion, "1.0.0.0");
input_value.SetString(keys::kName, "my extension");
- EXPECT_TRUE(extension.InitFromValue(input_value, false, NULL));
-
- EXPECT_EQ(extension.url().spec() + "bar/baz.js",
- Extension::GetResourceURL(extension.url(), "bar/baz.js").spec());
- EXPECT_EQ(extension.url().spec() + "baz.js",
- Extension::GetResourceURL(extension.url(), "bar/../baz.js").spec());
- EXPECT_EQ(extension.url().spec() + "baz.js",
- Extension::GetResourceURL(extension.url(), "../baz.js").spec());
+ scoped_refptr<Extension> extension(Extension::Create(
+ path, Extension::INVALID, input_value, false, NULL));
+ EXPECT_TRUE(extension.get());
+
+ EXPECT_EQ(extension->url().spec() + "bar/baz.js",
+ Extension::GetResourceURL(extension->url(), "bar/baz.js").spec());
+ EXPECT_EQ(extension->url().spec() + "baz.js",
+ Extension::GetResourceURL(extension->url(),
+ "bar/../baz.js").spec());
+ EXPECT_EQ(extension->url().spec() + "baz.js",
+ Extension::GetResourceURL(extension->url(), "../baz.js").spec());
}
TEST(ExtensionTest, LoadPageActionHelper) {
#if defined(OS_WIN)
- FilePath path(StringPrintf(L"c:\\extension"));
+ FilePath path(base::StringPrintf(L"c:\\extension"));
#else
- FilePath path(StringPrintf("/extension"));
+ FilePath path(base::StringPrintf("/extension"));
#endif
- Extension extension(path);
+ scoped_refptr<Extension> extension_ptr(new Extension(path,
+ Extension::INVALID));
+ Extension& extension = *extension_ptr;
std::string error_msg;
scoped_ptr<ExtensionAction> action;
DictionaryValue input;
@@ -539,7 +549,7 @@ TEST(ExtensionTest, LoadPageActionHelper) {
// LoadExtensionActionHelper expects the extension member |extension_url|
// to be set.
- extension.mutable_static_data_->extension_url =
+ extension.extension_url_ =
GURL(std::string(chrome::kExtensionScheme) +
chrome::kStandardSchemeSeparator +
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/");
@@ -651,18 +661,19 @@ TEST(ExtensionTest, UpdateUrls) {
#if defined(OS_WIN)
// (Why %Iu below? This is the single file in the whole code base that
// might make use of a WidePRIuS; let's not encourage any more.)
- FilePath path(StringPrintf(L"c:\\extension%Iu", i));
+ FilePath path(base::StringPrintf(L"c:\\extension%Iu", i));
#else
- FilePath path(StringPrintf("/extension%" PRIuS, i));
+ FilePath path(base::StringPrintf("/extension%" PRIuS, i));
#endif
- Extension extension(path);
std::string error;
input_value.SetString(keys::kVersion, "1.0");
input_value.SetString(keys::kName, "Test");
input_value.SetString(keys::kUpdateURL, url.spec());
- EXPECT_TRUE(extension.InitFromValue(input_value, false, &error));
+ scoped_refptr<Extension> extension(Extension::Create(
+ path, Extension::INVALID, input_value, false, &error));
+ EXPECT_TRUE(extension.get()) << error;
}
// Test some invalid update urls
@@ -675,17 +686,18 @@ TEST(ExtensionTest, UpdateUrls) {
#if defined(OS_WIN)
// (Why %Iu below? This is the single file in the whole code base that
// might make use of a WidePRIuS; let's not encourage any more.)
- FilePath path(StringPrintf(L"c:\\extension%Iu", i));
+ FilePath path(base::StringPrintf(L"c:\\extension%Iu", i));
#else
- FilePath path(StringPrintf("/extension%" PRIuS, i));
+ FilePath path(base::StringPrintf("/extension%" PRIuS, i));
#endif
- Extension extension(path);
std::string error;
input_value.SetString(keys::kVersion, "1.0");
input_value.SetString(keys::kName, "Test");
input_value.SetString(keys::kUpdateURL, invalid[i]);
- EXPECT_FALSE(extension.InitFromValue(input_value, false, &error));
+ scoped_refptr<Extension> extension(Extension::Create(
+ path, Extension::INVALID, input_value, false, &error));
+ EXPECT_FALSE(extension.get());
EXPECT_TRUE(MatchPattern(error, errors::kInvalidUpdateURL));
}
}
@@ -714,8 +726,8 @@ TEST(ExtensionTest, MimeTypeSniffing) {
EXPECT_EQ("application/octet-stream", result);
}
-static Extension* LoadManifest(const std::string& dir,
- const std::string& test_file) {
+static scoped_refptr<Extension> LoadManifest(const std::string& dir,
+ const std::string& test_file) {
FilePath path;
PathService::Get(chrome::DIR_TEST_DATA, &path);
path = path.AppendASCII("extensions")
@@ -730,74 +742,70 @@ static Extension* LoadManifest(const std::string& dir,
return NULL;
}
- scoped_ptr<Extension> extension(new Extension(path.DirName()));
- EXPECT_TRUE(extension->InitFromValue(
- *static_cast<DictionaryValue*>(result.get()), false, &error)) << error;
-
- return extension.release();
+ scoped_refptr<Extension> extension = Extension::Create(
+ path.DirName(), Extension::INVALID,
+ *static_cast<DictionaryValue*>(result.get()), false, &error);
+ EXPECT_TRUE(extension) << error;
+ return extension;
}
TEST(ExtensionTest, EffectiveHostPermissions) {
- scoped_ptr<Extension> extension;
+ scoped_refptr<Extension> extension;
ExtensionExtent hosts;
- extension.reset(LoadManifest("effective_host_permissions", "empty.json"));
+ extension = LoadManifest("effective_host_permissions", "empty.json");
EXPECT_EQ(0u, extension->GetEffectiveHostPermissions().patterns().size());
EXPECT_FALSE(hosts.ContainsURL(GURL("http://www.google.com")));
EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
- extension.reset(LoadManifest("effective_host_permissions", "one_host.json"));
+ extension = LoadManifest("effective_host_permissions", "one_host.json");
hosts = extension->GetEffectiveHostPermissions();
EXPECT_TRUE(hosts.ContainsURL(GURL("http://www.google.com")));
EXPECT_FALSE(hosts.ContainsURL(GURL("https://www.google.com")));
EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
- extension.reset(LoadManifest("effective_host_permissions",
- "one_host_wildcard.json"));
+ extension = LoadManifest("effective_host_permissions",
+ "one_host_wildcard.json");
hosts = extension->GetEffectiveHostPermissions();
EXPECT_TRUE(hosts.ContainsURL(GURL("http://google.com")));
EXPECT_TRUE(hosts.ContainsURL(GURL("http://foo.google.com")));
EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
- extension.reset(LoadManifest("effective_host_permissions",
- "two_hosts.json"));
+ extension = LoadManifest("effective_host_permissions", "two_hosts.json");
hosts = extension->GetEffectiveHostPermissions();
EXPECT_TRUE(hosts.ContainsURL(GURL("http://www.google.com")));
EXPECT_TRUE(hosts.ContainsURL(GURL("http://www.reddit.com")));
EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
- extension.reset(LoadManifest("effective_host_permissions",
- "https_not_considered.json"));
+ extension = LoadManifest("effective_host_permissions",
+ "https_not_considered.json");
hosts = extension->GetEffectiveHostPermissions();
EXPECT_TRUE(hosts.ContainsURL(GURL("http://google.com")));
EXPECT_TRUE(hosts.ContainsURL(GURL("https://google.com")));
EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
- extension.reset(LoadManifest("effective_host_permissions",
- "two_content_scripts.json"));
+ extension = LoadManifest("effective_host_permissions",
+ "two_content_scripts.json");
hosts = extension->GetEffectiveHostPermissions();
EXPECT_TRUE(hosts.ContainsURL(GURL("http://google.com")));
EXPECT_TRUE(hosts.ContainsURL(GURL("http://www.reddit.com")));
EXPECT_TRUE(hosts.ContainsURL(GURL("http://news.ycombinator.com")));
EXPECT_FALSE(extension->HasEffectiveAccessToAllHosts());
- extension.reset(LoadManifest("effective_host_permissions",
- "all_hosts.json"));
+ extension = LoadManifest("effective_host_permissions", "all_hosts.json");
hosts = extension->GetEffectiveHostPermissions();
EXPECT_TRUE(hosts.ContainsURL(GURL("http://test/")));
EXPECT_FALSE(hosts.ContainsURL(GURL("https://test/")));
EXPECT_TRUE(hosts.ContainsURL(GURL("http://www.google.com")));
EXPECT_TRUE(extension->HasEffectiveAccessToAllHosts());
- extension.reset(LoadManifest("effective_host_permissions",
- "all_hosts2.json"));
+ extension = LoadManifest("effective_host_permissions", "all_hosts2.json");
hosts = extension->GetEffectiveHostPermissions();
EXPECT_TRUE(hosts.ContainsURL(GURL("http://test/")));
EXPECT_TRUE(hosts.ContainsURL(GURL("http://www.google.com")));
EXPECT_TRUE(extension->HasEffectiveAccessToAllHosts());
- extension.reset(LoadManifest("effective_host_permissions",
- "all_hosts3.json"));
+ extension = LoadManifest("effective_host_permissions", "all_hosts3.json");
hosts = extension->GetEffectiveHostPermissions();
EXPECT_FALSE(hosts.ContainsURL(GURL("http://test/")));
EXPECT_TRUE(hosts.ContainsURL(GURL("https://test/")));
@@ -834,10 +842,10 @@ TEST(ExtensionTest, IsPrivilegeIncrease) {
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
- scoped_ptr<Extension> old_extension(
+ scoped_refptr<Extension> old_extension(
LoadManifest("allow_silent_upgrade",
std::string(kTests[i].base_name) + "_old.json"));
- scoped_ptr<Extension> new_extension(
+ scoped_refptr<Extension> new_extension(
LoadManifest("allow_silent_upgrade",
std::string(kTests[i].base_name) + "_new.json"));
@@ -912,11 +920,12 @@ TEST(ExtensionTest, ImageCaching) {
// Initialize the Extension.
std::string errors;
- scoped_ptr<Extension> extension(new Extension(path));
DictionaryValue values;
values.SetString(keys::kName, "test");
values.SetString(keys::kVersion, "0.1");
- ASSERT_TRUE(extension->InitFromValue(values, false, &errors));
+ scoped_refptr<Extension> extension(Extension::Create(
+ path, Extension::INVALID, values, false, &errors));
+ ASSERT_TRUE(extension.get());
// Create an ExtensionResource pointing at an icon.
FilePath icon_relative_path(FILE_PATH_LITERAL("icon3.png"));
@@ -997,10 +1006,11 @@ TEST(ExtensionTest, OldUnlimitedStoragePermission) {
// Initialize the extension and make sure the permission for unlimited storage
// is present.
- Extension extension(extension_path);
std::string errors;
- EXPECT_TRUE(extension.InitFromValue(dictionary, false, &errors));
- EXPECT_TRUE(extension.HasApiPermission(
+ scoped_refptr<Extension> extension(Extension::Create(
+ extension_path, Extension::INVALID, dictionary, false, &errors));
+ EXPECT_TRUE(extension.get());
+ EXPECT_TRUE(extension->HasApiPermission(
Extension::kUnlimitedStoragePermission));
}
@@ -1036,8 +1046,8 @@ TEST(ExtensionTest, ApiPermissions) {
{ "tabs.getSelected", false},
};
- scoped_ptr<Extension> extension;
- extension.reset(LoadManifest("empty_manifest", "empty.json"));
+ scoped_refptr<Extension> extension;
+ extension = LoadManifest("empty_manifest", "empty.json");
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
EXPECT_EQ(kTests[i].expect_success,
diff --git a/chrome/common/extensions/extension_unpacker.cc b/chrome/common/extensions/extension_unpacker.cc
index d431bcb..e270870 100644
--- a/chrome/common/extensions/extension_unpacker.cc
+++ b/chrome/common/extensions/extension_unpacker.cc
@@ -175,20 +175,21 @@ bool ExtensionUnpacker::Run() {
// InitFromValue is allowed to generate a temporary id for the extension.
// ANY CODE THAT FOLLOWS SHOULD NOT DEPEND ON THE CORRECT ID OF THIS
// EXTENSION.
- Extension extension(temp_install_dir_);
std::string error;
- if (!extension.InitFromValue(*parsed_manifest_, false, &error)) {
+ scoped_refptr<Extension> extension(Extension::Create(
+ temp_install_dir_, Extension::INVALID, *parsed_manifest_, false, &error));
+ if (!extension.get()) {
SetError(error);
return false;
}
- if (!extension_file_util::ValidateExtension(&extension, &error)) {
+ if (!extension_file_util::ValidateExtension(extension.get(), &error)) {
SetError(error);
return false;
}
// Decode any images that the browser needs to display.
- std::set<FilePath> image_paths = extension.GetBrowserImages();
+ std::set<FilePath> image_paths = extension->GetBrowserImages();
for (std::set<FilePath>::iterator it = image_paths.begin();
it != image_paths.end(); ++it) {
if (!AddDecodedImage(*it))
@@ -197,8 +198,8 @@ bool ExtensionUnpacker::Run() {
// Parse all message catalogs (if any).
parsed_catalogs_.reset(new DictionaryValue);
- if (!extension.default_locale().empty()) {
- if (!ReadAllMessageCatalogs(extension.default_locale()))
+ if (!extension->default_locale().empty()) {
+ if (!ReadAllMessageCatalogs(extension->default_locale()))
return false; // Error was already reported.
}
@@ -288,10 +289,11 @@ bool ExtensionUnpacker::ReadMessageCatalog(const FilePath& message_path) {
std::string messages_file = WideToASCII(message_path.ToWStringHack());
if (error.empty()) {
// If file is missing, Deserialize will fail with empty error.
- SetError(StringPrintf("%s %s", errors::kLocalesMessagesFileMissing,
- messages_file.c_str()));
+ SetError(base::StringPrintf("%s %s", errors::kLocalesMessagesFileMissing,
+ messages_file.c_str()));
} else {
- SetError(StringPrintf("%s: %s", messages_file.c_str(), error.c_str()));
+ SetError(base::StringPrintf("%s: %s", messages_file.c_str(),
+ error.c_str()));
}
return false;
}
diff --git a/chrome/common/extensions/url_pattern.cc b/chrome/common/extensions/url_pattern.cc
index aa7e252..b6e09b7 100644
--- a/chrome/common/extensions/url_pattern.cc
+++ b/chrome/common/extensions/url_pattern.cc
@@ -58,14 +58,14 @@ URLPattern::URLPattern(int valid_schemes)
URLPattern::URLPattern(int valid_schemes, const std::string& pattern)
: valid_schemes_(valid_schemes), match_all_urls_(false),
match_subdomains_(false) {
- if (!Parse(pattern))
+ if (PARSE_SUCCESS != Parse(pattern))
NOTREACHED() << "URLPattern is invalid: " << pattern;
}
URLPattern::~URLPattern() {
}
-bool URLPattern::Parse(const std::string& pattern) {
+URLPattern::ParseResult URLPattern::Parse(const std::string& pattern) {
// Special case pattern to match every valid URL.
if (pattern == kAllUrlsPattern) {
match_all_urls_ = true;
@@ -73,40 +73,51 @@ bool URLPattern::Parse(const std::string& pattern) {
scheme_ = "*";
host_.clear();
path_ = "/*";
- return true;
+ return PARSE_SUCCESS;
+ }
+
+ // Parse out the scheme.
+ size_t scheme_end_pos = pattern.find(chrome::kStandardSchemeSeparator);
+ bool has_standard_scheme_separator = true;
+
+ // Some urls also use ':' alone as the scheme separator.
+ if (scheme_end_pos == std::string::npos) {
+ scheme_end_pos = pattern.find(':');
+ has_standard_scheme_separator = false;
}
- size_t scheme_end_pos = pattern.find(":");
if (scheme_end_pos == std::string::npos)
- return false;
+ return PARSE_ERROR_MISSING_SCHEME_SEPARATOR;
if (!SetScheme(pattern.substr(0, scheme_end_pos)))
- return false;
+ return PARSE_ERROR_INVALID_SCHEME;
- std::string separator =
- pattern.substr(scheme_end_pos, strlen(chrome::kStandardSchemeSeparator));
- if (separator == chrome::kStandardSchemeSeparator)
- scheme_end_pos += strlen(chrome::kStandardSchemeSeparator);
- else
- scheme_end_pos += 1;
+ bool standard_scheme = IsStandardScheme(scheme_);
+ if (standard_scheme != has_standard_scheme_separator)
+ return PARSE_ERROR_WRONG_SCHEME_SEPARATOR;
// Advance past the scheme separator.
- size_t host_start_pos = scheme_end_pos;
- if (host_start_pos >= pattern.length())
- return false;
+ scheme_end_pos +=
+ (standard_scheme ? strlen(chrome::kStandardSchemeSeparator) : 1);
+ if (scheme_end_pos >= pattern.size())
+ return PARSE_ERROR_EMPTY_HOST;
// Parse out the host and path.
+ size_t host_start_pos = scheme_end_pos;
size_t path_start_pos = 0;
- bool standard_scheme = IsStandardScheme(scheme_);
-
// File URLs are special because they have no host.
if (scheme_ == chrome::kFileScheme || !standard_scheme) {
path_start_pos = host_start_pos;
} else {
size_t host_end_pos = pattern.find(kPathSeparator, host_start_pos);
+
+ // Host is required.
+ if (host_start_pos == host_end_pos)
+ return PARSE_ERROR_EMPTY_HOST;
+
if (host_end_pos == std::string::npos)
- return false;
+ return PARSE_ERROR_EMPTY_PATH;
host_ = pattern.substr(host_start_pos, host_end_pos - host_start_pos);
@@ -124,14 +135,14 @@ bool URLPattern::Parse(const std::string& pattern) {
// done as a convenience to developers who might otherwise be confused and
// think '*' works as a glob in the host.
if (host_.find('*') != std::string::npos)
- return false;
+ return PARSE_ERROR_INVALID_HOST_WILDCARD;
path_start_pos = host_end_pos;
}
path_ = pattern.substr(path_start_pos);
- return true;
+ return PARSE_SUCCESS;
}
bool URLPattern::SetScheme(const std::string& scheme) {
diff --git a/chrome/common/extensions/url_pattern.h b/chrome/common/extensions/url_pattern.h
index 832673c..72810ba 100644
--- a/chrome/common/extensions/url_pattern.h
+++ b/chrome/common/extensions/url_pattern.h
@@ -91,13 +91,20 @@ class URLPattern {
SCHEME_ALL = -1,
};
+ // Error codes returned from Parse().
+ enum ParseResult {
+ PARSE_SUCCESS,
+ PARSE_ERROR_MISSING_SCHEME_SEPARATOR,
+ PARSE_ERROR_INVALID_SCHEME,
+ PARSE_ERROR_WRONG_SCHEME_SEPARATOR,
+ PARSE_ERROR_EMPTY_HOST,
+ PARSE_ERROR_INVALID_HOST_WILDCARD,
+ PARSE_ERROR_EMPTY_PATH,
+ };
+
// The <all_urls> string pattern.
static const char kAllUrlsPattern[];
- // Note: don't use this directly. This exists so URLPattern can be used
- // with STL containers.
- URLPattern();
-
// Construct an URLPattern with the given set of allowable schemes. See
// valid_schemes_ for more info.
explicit URLPattern(int valid_schemes);
@@ -134,9 +141,11 @@ class URLPattern {
bool match_all_urls() const { return match_all_urls_; }
void set_match_all_urls(bool val) { match_all_urls_ = val; }
- // Initializes this instance by parsing the provided string. On failure, the
- // instance will have some intermediate values and is in an invalid state.
- bool Parse(const std::string& pattern_str);
+ // Initializes this instance by parsing the provided string. Returns
+ // URLPattern::PARSE_SUCCESS on success, or an error code otherwise. On
+ // failure, this instance will have some intermediate values and is in an
+ // invalid state.
+ ParseResult Parse(const std::string& pattern_str);
// Sets the scheme for pattern matches. This can be a single '*' if the
// pattern matches all valid schemes (as defined by the valid_schemes_
@@ -192,6 +201,21 @@ class URLPattern {
};
private:
+ friend class std::vector<URLPattern>;
+
+// See clang bug: http://llvm.org/bugs/show_bug.cgi?id=8479
+#if defined(__clang__)
+ public:
+#endif
+
+ // Note: don't use this directly. This exists so URLPattern can be used
+ // with STL containers.
+ URLPattern();
+
+#if defined(__clang__)
+ private:
+#endif
+
// A bitmask containing the schemes which are considered valid for this
// pattern. Parse() uses this to decide whether a pattern contains a valid
// scheme. MatchesScheme uses this to decide whether a wildcard scheme_
diff --git a/chrome/common/extensions/url_pattern_unittest.cc b/chrome/common/extensions/url_pattern_unittest.cc
index a9ef21e..e0be087 100644
--- a/chrome/common/extensions/url_pattern_unittest.cc
+++ b/chrome/common/extensions/url_pattern_unittest.cc
@@ -17,29 +17,34 @@ static const int kAllSchemes =
URLPattern::SCHEME_CHROMEUI;
TEST(URLPatternTest, ParseInvalid) {
- const char* kInvalidPatterns[] = {
- "http", // no scheme
- "http:",
- "http:/",
- "http://", // no path separator
- "http://foo", // no path separator
- "http://*foo/bar", // not allowed as substring of host component
- "http://foo.*.bar/baz", // must be first component
- "http:/bar", // scheme separator not found
- "foo://*", // invalid scheme
- "chrome-extension://*/*", // we don't support chrome extension URLs
+ const struct {
+ const char* pattern;
+ URLPattern::ParseResult expected_result;
+ } kInvalidPatterns[] = {
+ { "http", URLPattern::PARSE_ERROR_MISSING_SCHEME_SEPARATOR },
+ { "http:", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
+ { "http:/", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
+ { "about://", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
+ { "http://", URLPattern::PARSE_ERROR_EMPTY_HOST },
+ { "http:///", URLPattern::PARSE_ERROR_EMPTY_HOST },
+ { "http://*foo/bar", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD },
+ { "http://foo.*.bar/baz", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD },
+ { "http:/bar", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
+ { "http://bar", URLPattern::PARSE_ERROR_EMPTY_PATH },
};
- for (size_t i = 0; i < arraysize(kInvalidPatterns); ++i) {
- URLPattern pattern;
- EXPECT_FALSE(pattern.Parse(kInvalidPatterns[i])) << kInvalidPatterns[i];
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kInvalidPatterns); ++i) {
+ URLPattern pattern(URLPattern::SCHEME_ALL);
+ EXPECT_EQ(kInvalidPatterns[i].expected_result,
+ pattern.Parse(kInvalidPatterns[i].pattern))
+ << kInvalidPatterns[i].pattern;
}
};
// all pages for a given scheme
TEST(URLPatternTest, Match1) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("http://*/*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://*/*"));
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -55,7 +60,7 @@ TEST(URLPatternTest, Match1) {
// all domains
TEST(URLPatternTest, Match2) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("https://*/foo*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("https://*/foo*"));
EXPECT_EQ("https", pattern.scheme());
EXPECT_EQ("", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -70,7 +75,8 @@ TEST(URLPatternTest, Match2) {
// subdomains
TEST(URLPatternTest, Match3) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("http://*.google.com/foo*bar"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("http://*.google.com/foo*bar"));
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("google.com", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -86,7 +92,8 @@ TEST(URLPatternTest, Match3) {
// glob escaping
TEST(URLPatternTest, Match5) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("file:///foo?bar\\*baz"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("file:///foo?bar\\*baz"));
EXPECT_EQ("file", pattern.scheme());
EXPECT_EQ("", pattern.host());
EXPECT_FALSE(pattern.match_subdomains());
@@ -99,7 +106,8 @@ TEST(URLPatternTest, Match5) {
// ip addresses
TEST(URLPatternTest, Match6) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("http://127.0.0.1/*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("http://127.0.0.1/*"));
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("127.0.0.1", pattern.host());
EXPECT_FALSE(pattern.match_subdomains());
@@ -111,7 +119,8 @@ TEST(URLPatternTest, Match6) {
// subdomain matching with ip addresses
TEST(URLPatternTest, Match7) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("http://*.0.0.1/*")); // allowed, but useless
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("http://*.0.0.1/*")); // allowed, but useless
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("0.0.1", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -126,7 +135,8 @@ TEST(URLPatternTest, Match8) {
URLPattern pattern(kAllSchemes);
// The below is the ASCII encoding of the following URL:
// http://*.\xe1\x80\xbf/a\xc2\x81\xe1*
- EXPECT_TRUE(pattern.Parse("http://*.xn--gkd/a%C2%81%E1*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("http://*.xn--gkd/a%C2%81%E1*"));
EXPECT_EQ("http", pattern.scheme());
EXPECT_EQ("xn--gkd", pattern.host());
EXPECT_TRUE(pattern.match_subdomains());
@@ -141,7 +151,8 @@ TEST(URLPatternTest, Match8) {
// chrome://
TEST(URLPatternTest, Match9) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("chrome://favicon/*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("chrome://favicon/*"));
EXPECT_EQ("chrome", pattern.scheme());
EXPECT_EQ("favicon", pattern.host());
EXPECT_FALSE(pattern.match_subdomains());
@@ -155,7 +166,7 @@ TEST(URLPatternTest, Match9) {
// *://
TEST(URLPatternTest, Match10) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("*://*/*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("*://*/*"));
EXPECT_TRUE(pattern.MatchesScheme("http"));
EXPECT_TRUE(pattern.MatchesScheme("https"));
EXPECT_FALSE(pattern.MatchesScheme("chrome"));
@@ -172,7 +183,7 @@ TEST(URLPatternTest, Match10) {
// <all_urls>
TEST(URLPatternTest, Match11) {
URLPattern pattern(kAllSchemes);
- EXPECT_TRUE(pattern.Parse("<all_urls>"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("<all_urls>"));
EXPECT_TRUE(pattern.MatchesScheme("chrome"));
EXPECT_TRUE(pattern.MatchesScheme("http"));
EXPECT_TRUE(pattern.MatchesScheme("https"));
@@ -188,7 +199,7 @@ TEST(URLPatternTest, Match11) {
// SCHEME_ALL matches all schemes.
TEST(URLPatternTest, Match12) {
URLPattern pattern(URLPattern::SCHEME_ALL);
- EXPECT_TRUE(pattern.Parse("<all_urls>"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("<all_urls>"));
EXPECT_TRUE(pattern.MatchesScheme("chrome"));
EXPECT_TRUE(pattern.MatchesScheme("http"));
EXPECT_TRUE(pattern.MatchesScheme("https"));
@@ -226,7 +237,8 @@ static const struct MatchPatterns {
TEST(URLPatternTest, Match13) {
for (size_t i = 0; i < arraysize(kMatch13UrlPatternTestCases); ++i) {
URLPattern pattern(URLPattern::SCHEME_ALL);
- EXPECT_TRUE(pattern.Parse(kMatch13UrlPatternTestCases[i].pattern))
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse(kMatch13UrlPatternTestCases[i].pattern))
<< " while parsing " << kMatch13UrlPatternTestCases[i].pattern;
EXPECT_TRUE(pattern.MatchesUrl(
GURL(kMatch13UrlPatternTestCases[i].matches)))
@@ -235,7 +247,7 @@ TEST(URLPatternTest, Match13) {
// Negative test.
URLPattern pattern(URLPattern::SCHEME_ALL);
- EXPECT_TRUE(pattern.Parse("data:*"));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("data:*"));
EXPECT_FALSE(pattern.MatchesUrl(GURL("about:blank")));
};
@@ -259,7 +271,8 @@ static const struct GetAsStringPatterns {
TEST(URLPatternTest, GetAsString) {
for (size_t i = 0; i < arraysize(kGetAsStringTestCases); ++i) {
URLPattern pattern(URLPattern::SCHEME_ALL);
- EXPECT_TRUE(pattern.Parse(kGetAsStringTestCases[i].pattern));
+ EXPECT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse(kGetAsStringTestCases[i].pattern));
EXPECT_STREQ(kGetAsStringTestCases[i].pattern,
pattern.GetAsString().c_str());
}
diff --git a/chrome/common/extensions/user_script.cc b/chrome/common/extensions/user_script.cc
index cea7cf6..f71de5c 100644
--- a/chrome/common/extensions/user_script.cc
+++ b/chrome/common/extensions/user_script.cc
@@ -195,7 +195,7 @@ void UserScript::Unpickle(const ::Pickle& pickle, void** iter) {
std::string pattern_str;
URLPattern pattern(valid_schemes);
CHECK(pickle.ReadString(iter, &pattern_str));
- CHECK(pattern.Parse(pattern_str));
+ CHECK(URLPattern::PARSE_SUCCESS == pattern.Parse(pattern_str));
url_patterns_.push_back(pattern);
}
diff --git a/chrome/common/extensions/user_script_unittest.cc b/chrome/common/extensions/user_script_unittest.cc
index ab3e218..949ad1a 100644
--- a/chrome/common/extensions/user_script_unittest.cc
+++ b/chrome/common/extensions/user_script_unittest.cc
@@ -71,7 +71,7 @@ TEST(UserScriptTest, Match5) {
TEST(UserScriptTest, Match6) {
URLPattern pattern(kAllSchemes);
- ASSERT_TRUE(pattern.Parse("http://*/foo*"));
+ ASSERT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://*/foo*"));
UserScript script;
script.add_url_pattern(pattern);
@@ -86,7 +86,8 @@ TEST(UserScriptTest, UrlPatternGlobInteraction) {
UserScript script;
URLPattern pattern(kAllSchemes);
- ASSERT_TRUE(pattern.Parse("http://www.google.com/*"));
+ ASSERT_EQ(URLPattern::PARSE_SUCCESS,
+ pattern.Parse("http://www.google.com/*"));
script.add_url_pattern(pattern);
script.add_glob("*bar*");
@@ -114,8 +115,8 @@ TEST(UserScriptTest, UrlPatternGlobInteraction) {
TEST(UserScriptTest, Pickle) {
URLPattern pattern1(kAllSchemes);
URLPattern pattern2(kAllSchemes);
- ASSERT_TRUE(pattern1.Parse("http://*/foo*"));
- ASSERT_TRUE(pattern2.Parse("http://bar/baz*"));
+ ASSERT_EQ(URLPattern::PARSE_SUCCESS, pattern1.Parse("http://*/foo*"));
+ ASSERT_EQ(URLPattern::PARSE_SUCCESS, pattern2.Parse("http://bar/baz*"));
UserScript script1;
script1.js_scripts().push_back(UserScript::File(
diff --git a/chrome/common/file_system/file_system_dispatcher.cc b/chrome/common/file_system/file_system_dispatcher.cc
index dfe23bf..352deb3 100644
--- a/chrome/common/file_system/file_system_dispatcher.cc
+++ b/chrome/common/file_system/file_system_dispatcher.cc
@@ -41,10 +41,11 @@ bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
bool FileSystemDispatcher::OpenFileSystem(
const GURL& origin_url, fileapi::FileSystemType type,
- long long size, fileapi::FileSystemCallbackDispatcher* dispatcher) {
+ long long size, bool create,
+ fileapi::FileSystemCallbackDispatcher* dispatcher) {
int request_id = dispatchers_.Add(dispatcher);
if (!ChildThread::current()->Send(new ViewHostMsg_OpenFileSystemRequest(
- request_id, origin_url, type, size))) {
+ request_id, origin_url, type, size, create))) {
dispatchers_.Remove(request_id); // destroys |dispatcher|
return false;
}
@@ -247,7 +248,7 @@ void FileSystemDispatcher::DidReadMetadata(
void FileSystemDispatcher::DidReadDirectory(
int request_id,
- const std::vector<base::file_util_proxy::Entry>& entries,
+ const std::vector<base::FileUtilProxy::Entry>& entries,
bool has_more) {
fileapi::FileSystemCallbackDispatcher* dispatcher =
dispatchers_.Lookup(request_id);
diff --git a/chrome/common/file_system/file_system_dispatcher.h b/chrome/common/file_system/file_system_dispatcher.h
index f256189..b8ffb2c 100644
--- a/chrome/common/file_system/file_system_dispatcher.h
+++ b/chrome/common/file_system/file_system_dispatcher.h
@@ -35,6 +35,7 @@ class FileSystemDispatcher {
bool OpenFileSystem(const GURL& origin_url,
fileapi::FileSystemType type,
long long size,
+ bool create,
fileapi::FileSystemCallbackDispatcher* dispatcher);
bool Move(const FilePath& src_path,
const FilePath& dest_path,
@@ -87,7 +88,7 @@ class FileSystemDispatcher {
const base::PlatformFileInfo& file_info);
void DidReadDirectory(
int request_id,
- const std::vector<base::file_util_proxy::Entry>& entries,
+ const std::vector<base::FileUtilProxy::Entry>& entries,
bool has_more);
void DidFail(int request_id, base::PlatformFileError error_code);
void DidWrite(int request_id, int64 bytes, bool complete);
diff --git a/chrome/common/file_system/webfilesystem_callback_dispatcher.cc b/chrome/common/file_system/webfilesystem_callback_dispatcher.cc
index bf8d901..6d779a2 100644
--- a/chrome/common/file_system/webfilesystem_callback_dispatcher.cc
+++ b/chrome/common/file_system/webfilesystem_callback_dispatcher.cc
@@ -41,7 +41,7 @@ void WebFileSystemCallbackDispatcher::DidReadMetadata(
}
void WebFileSystemCallbackDispatcher::DidReadDirectory(
- const std::vector<base::file_util_proxy::Entry>& entries, bool has_more) {
+ const std::vector<base::FileUtilProxy::Entry>& entries, bool has_more) {
WebVector<WebFileSystemEntry> file_system_entries(entries.size());
for (size_t i = 0; i < entries.size(); i++) {
file_system_entries[i].name =
diff --git a/chrome/common/file_system/webfilesystem_callback_dispatcher.h b/chrome/common/file_system/webfilesystem_callback_dispatcher.h
index 075d5bb..dc570fa 100644
--- a/chrome/common/file_system/webfilesystem_callback_dispatcher.h
+++ b/chrome/common/file_system/webfilesystem_callback_dispatcher.h
@@ -9,12 +9,6 @@
#include "base/platform_file.h"
#include "webkit/fileapi/file_system_callback_dispatcher.h"
-namespace base {
-namespace file_util_proxy {
-struct Entry;
-}
-}
-
namespace WebKit {
class WebFileSystemCallbacks;
}
@@ -29,7 +23,7 @@ class WebFileSystemCallbackDispatcher
virtual void DidSucceed();
virtual void DidReadMetadata(const base::PlatformFileInfo& file_info);
virtual void DidReadDirectory(
- const std::vector<base::file_util_proxy::Entry>& entries,
+ const std::vector<base::FileUtilProxy::Entry>& entries,
bool has_more);
virtual void DidOpenFileSystem(const std::string&,
const FilePath&);
diff --git a/chrome/common/file_system/webfilewriter_impl.cc b/chrome/common/file_system/webfilewriter_impl.cc
index 2f3677b..7fc2656 100644
--- a/chrome/common/file_system/webfilewriter_impl.cc
+++ b/chrome/common/file_system/webfilewriter_impl.cc
@@ -12,7 +12,6 @@ namespace {
inline FileSystemDispatcher* GetFileSystemDispatcher() {
return ChildThread::current()->file_system_dispatcher();
}
-
}
class WebFileWriterImpl::CallbackDispatcher
@@ -28,7 +27,7 @@ class WebFileWriterImpl::CallbackDispatcher
NOTREACHED();
}
virtual void DidReadDirectory(
- const std::vector<base::file_util_proxy::Entry>& entries,
+ const std::vector<base::FileUtilProxy::Entry>& entries,
bool has_more) {
NOTREACHED();
}
@@ -78,4 +77,3 @@ void WebFileWriterImpl::DoCancel() {
GetFileSystemDispatcher()->Cancel(request_id_,
new CallbackDispatcher(AsWeakPtr()));
}
-
diff --git a/chrome/common/font_loader_mac.mm b/chrome/common/font_loader_mac.mm
index a5bb781..3ab57c4 100644
--- a/chrome/common/font_loader_mac.mm
+++ b/chrome/common/font_loader_mac.mm
@@ -65,16 +65,11 @@ bool FontLoader::LoadFontIntoBuffer(NSFont* font_to_encode,
}
int32 font_file_size_32 = static_cast<int32>(font_file_size_64);
- if (!font_data->Create("", false, false, font_file_size_32)) {
+ if (!font_data->CreateAndMapAnonymous(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);
diff --git a/chrome/common/gpu_create_command_buffer_config.cc b/chrome/common/gpu_create_command_buffer_config.cc
new file mode 100644
index 0000000..e8ab9d7
--- /dev/null
+++ b/chrome/common/gpu_create_command_buffer_config.cc
@@ -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.
+
+#include "chrome/common/gpu_create_command_buffer_config.h"
+
+GPUCreateCommandBufferConfig::GPUCreateCommandBufferConfig() {}
+
+GPUCreateCommandBufferConfig::GPUCreateCommandBufferConfig(
+ const std::string& _allowed_extensions,
+ const std::vector<int>& _attribs)
+ : allowed_extensions(_allowed_extensions),
+ attribs(_attribs) {
+}
+
+GPUCreateCommandBufferConfig::~GPUCreateCommandBufferConfig() {}
diff --git a/chrome/common/gpu_create_command_buffer_config.h b/chrome/common/gpu_create_command_buffer_config.h
index 8a2525f..0cb217a 100644
--- a/chrome/common/gpu_create_command_buffer_config.h
+++ b/chrome/common/gpu_create_command_buffer_config.h
@@ -11,14 +11,12 @@
// Parameters passed when initializing a GPU channel.
struct GPUCreateCommandBufferConfig {
- GPUCreateCommandBufferConfig() { }
+ GPUCreateCommandBufferConfig();
- GPUCreateCommandBufferConfig(
- const std::string& _allowed_extensions,
- const std::vector<int>& _attribs)
- : allowed_extensions(_allowed_extensions),
- attribs(_attribs) {
- }
+ GPUCreateCommandBufferConfig(const std::string& _allowed_extensions,
+ const std::vector<int>& _attribs);
+
+ ~GPUCreateCommandBufferConfig();
std::string allowed_extensions;
std::vector<int> attribs;
diff --git a/chrome/common/gpu_info.cc b/chrome/common/gpu_info.cc
index 667c375..64f0498 100644
--- a/chrome/common/gpu_info.cc
+++ b/chrome/common/gpu_info.cc
@@ -16,6 +16,10 @@ bool GPUInfo::initialized() const {
return initialized_;
}
+base::TimeDelta GPUInfo::initialization_time() const {
+ return initialization_time_;
+}
+
uint32 GPUInfo::vendor_id() const {
return vendor_id_;
}
@@ -45,6 +49,12 @@ bool GPUInfo::can_lose_context() const {
return can_lose_context_;
}
+void GPUInfo::SetInitializationTime(
+ const base::TimeDelta& initialization_time) {
+ initialization_time_ = initialization_time;
+}
+
+
void GPUInfo::SetGraphicsInfo(uint32 vendor_id, uint32 device_id,
const std::wstring& driver_version,
uint32 pixel_shader_version,
diff --git a/chrome/common/gpu_info.h b/chrome/common/gpu_info.h
index 50728db..bdf8709 100644
--- a/chrome/common/gpu_info.h
+++ b/chrome/common/gpu_info.h
@@ -12,6 +12,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/time.h"
#include "build/build_config.h"
#include "chrome/common/dx_diag_node.h"
@@ -23,6 +24,10 @@ class GPUInfo {
// Returns whether this GPUInfo has been initialized with information
bool initialized() const;
+ // The amount of time taken to get from the process starting to the message
+ // loop being pumped.
+ base::TimeDelta initialization_time() const;
+
// Return the DWORD (uint32) representing the graphics card vendor id.
uint32 vendor_id() const;
@@ -55,6 +60,8 @@ class GPUInfo {
// semantics are available.
bool can_lose_context() const;
+ void SetInitializationTime(const base::TimeDelta& initialization_time);
+
// Populate variables with passed in values
void SetGraphicsInfo(uint32 vendor_id, uint32 device_id,
const std::wstring& driver_version,
@@ -72,6 +79,7 @@ class GPUInfo {
private:
bool initialized_;
+ base::TimeDelta initialization_time_;
uint32 vendor_id_;
uint32 device_id_;
std::wstring driver_version_;
diff --git a/chrome/common/gpu_messages.cc b/chrome/common/gpu_messages.cc
index db7f597..671a6a6 100644
--- a/chrome/common/gpu_messages.cc
+++ b/chrome/common/gpu_messages.cc
@@ -10,6 +10,7 @@
#include "gfx/rect.h"
#include "gfx/size.h"
#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message_utils.h"
#define MESSAGES_INTERNAL_IMPL_FILE \
"chrome/common/gpu_messages_internal.h"
@@ -80,6 +81,7 @@ void ParamTraits<GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params> ::Log(
#endif // if defined(OS_MACOSX)
void ParamTraits<GPUInfo> ::Write(Message* m, const param_type& p) {
+ ParamTraits<base::TimeDelta> ::Write(m, p.initialization_time());
m->WriteUInt32(p.vendor_id());
m->WriteUInt32(p.device_id());
m->WriteWString(p.driver_version());
@@ -94,6 +96,7 @@ void ParamTraits<GPUInfo> ::Write(Message* m, const param_type& p) {
}
bool ParamTraits<GPUInfo> ::Read(const Message* m, void** iter, param_type* p) {
+ base::TimeDelta initialization_time;
uint32 vendor_id;
uint32 device_id;
std::wstring driver_version;
@@ -101,13 +104,15 @@ bool ParamTraits<GPUInfo> ::Read(const Message* m, void** iter, param_type* p) {
uint32 vertex_shader_version;
uint32 gl_version;
bool can_lose_context;
- bool ret = m->ReadUInt32(iter, &vendor_id);
+ bool ret = ParamTraits<base::TimeDelta> ::Read(m, iter, &initialization_time);
+ ret = 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);
ret = ret && m->ReadUInt32(iter, &gl_version);
ret = ret && m->ReadBool(iter, &can_lose_context);
+ p->SetInitializationTime(initialization_time);
p->SetGraphicsInfo(vendor_id,
device_id,
driver_version,
@@ -126,11 +131,13 @@ bool ParamTraits<GPUInfo> ::Read(const Message* m, void** iter, param_type* p) {
}
void ParamTraits<GPUInfo> ::Log(const param_type& p, std::string* l) {
- l->append(StringPrintf("<GPUInfo> %x %x %ls %d",
- p.vendor_id(),
- p.device_id(),
- p.driver_version().c_str(),
- p.can_lose_context()));
+ l->append(base::StringPrintf("<GPUInfo> %d %x %x %ls %d",
+ static_cast<int32>(
+ p.initialization_time().InMilliseconds()),
+ p.vendor_id(),
+ p.device_id(),
+ p.driver_version().c_str(),
+ p.can_lose_context()));
}
void ParamTraits<DxDiagNode> ::Write(Message* m, const param_type& p) {
diff --git a/chrome/common/gpu_messages.h b/chrome/common/gpu_messages.h
index 799bc98..f932c99 100644
--- a/chrome/common/gpu_messages.h
+++ b/chrome/common/gpu_messages.h
@@ -9,7 +9,6 @@
#include "base/basictypes.h"
#include "base/process.h"
#include "chrome/common/common_param_traits.h"
-#include "chrome/common/gpu_native_window_handle.h"
#include "chrome/common/gpu_param_traits.h"
#include "gfx/native_widget_types.h"
#include "gpu/command_buffer/common/command_buffer.h"
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h
index 184d8f4..1b51c03 100644
--- a/chrome/common/gpu_messages_internal.h
+++ b/chrome/common/gpu_messages_internal.h
@@ -47,10 +47,6 @@ IPC_BEGIN_MESSAGES(Gpu)
// asynchronously.) Results in a GpuHostMsg_SynchronizeReply.
IPC_MESSAGE_CONTROL0(GpuMsg_Synchronize)
- IPC_MESSAGE_CONTROL2(GpuMsg_NewRenderWidgetHostView,
- GpuNativeWindowHandle, /* parent window */
- int32 /* view_id */)
-
// Tells the GPU process to create a context for collecting graphics card
// information.
IPC_MESSAGE_CONTROL0(GpuMsg_CollectGraphicsInfo)
@@ -61,45 +57,6 @@ IPC_BEGIN_MESSAGES(Gpu)
// Tells the GPU process to hang.
IPC_MESSAGE_CONTROL0(GpuMsg_Hang)
- // 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)
//------------------------------------------------------------------------------
@@ -107,12 +64,6 @@ IPC_END_MESSAGES(Gpu)
// 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 */
@@ -142,10 +93,11 @@ IPC_BEGIN_MESSAGES(GpuHost)
// This message notifies the browser process that the renderer
// swapped the buffers associated with the given "window", which
// should cause the browser to redraw the compositor's contents.
- IPC_MESSAGE_CONTROL3(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
+ IPC_MESSAGE_CONTROL4(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
int32, /* renderer_id */
int32, /* render_view_id */
- gfx::PluginWindowHandle /* window */)
+ gfx::PluginWindowHandle /* window */,
+ uint64 /* surface_id */)
#endif
IPC_END_MESSAGES(GpuHost)
diff --git a/chrome/common/gpu_messages_unittest.cc b/chrome/common/gpu_messages_unittest.cc
index 455458f..59d42ed 100644
--- a/chrome/common/gpu_messages_unittest.cc
+++ b/chrome/common/gpu_messages_unittest.cc
@@ -13,6 +13,7 @@
TEST(GPUIPCMessageTest, GPUInfo) {
GPUInfo input;
// Test variables taken from Lenovo T61
+ input.SetInitializationTime(base::TimeDelta::FromMilliseconds(100));
input.SetGraphicsInfo(0x10de, 0x429, L"6.14.11.7715",
0xffff0300,
0xfffe0300,
@@ -25,6 +26,8 @@ TEST(GPUIPCMessageTest, GPUInfo) {
GPUInfo output;
void* iter = NULL;
EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
+ EXPECT_EQ(input.initialization_time().InMilliseconds(),
+ output.initialization_time().InMilliseconds());
EXPECT_EQ(input.vendor_id(), output.vendor_id());
EXPECT_EQ(input.device_id(), output.device_id());
EXPECT_EQ(input.driver_version(), output.driver_version());
@@ -35,5 +38,5 @@ TEST(GPUIPCMessageTest, GPUInfo) {
std::string log_message;
IPC::LogParam(output, &log_message);
- EXPECT_STREQ("<GPUInfo> 10de 429 6.14.11.7715 1", log_message.c_str());
+ EXPECT_STREQ("<GPUInfo> 100 10de 429 6.14.11.7715 1", log_message.c_str());
}
diff --git a/chrome/common/gpu_native_window_handle.h b/chrome/common/gpu_native_window_handle.h
deleted file mode 100644
index cdc89f7..0000000
--- a/chrome/common/gpu_native_window_handle.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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_
-#pragma once
-
-#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_param_traits.h b/chrome/common/gpu_param_traits.h
index 59885ea..2aac31a 100644
--- a/chrome/common/gpu_param_traits.h
+++ b/chrome/common/gpu_param_traits.h
@@ -12,7 +12,6 @@
#include "chrome/common/dx_diag_node.h"
#include "chrome/common/gpu_create_command_buffer_config.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"
diff --git a/chrome/common/gpu_video_common.cc b/chrome/common/gpu_video_common.cc
index 67466b9..9e25a5f 100644
--- a/chrome/common/gpu_video_common.cc
+++ b/chrome/common/gpu_video_common.cc
@@ -28,7 +28,7 @@ bool ParamTraits<GpuVideoDecoderInitParam>::Read(
void ParamTraits<GpuVideoDecoderInitParam>::Log(
const GpuVideoDecoderInitParam& p, std::string* l) {
- l->append(StringPrintf("(%d, %d %d)", p.codec_id, p.width, p.height));
+ l->append(base::StringPrintf("(%d, %d %d)", p.codec_id, p.width, p.height));
}
///////////////////////////////////////////////////////////////////////////////
@@ -51,7 +51,7 @@ bool ParamTraits<GpuVideoDecoderInitDoneParam>::Read(
void ParamTraits<GpuVideoDecoderInitDoneParam>::Log(
const GpuVideoDecoderInitDoneParam& p, std::string* l) {
- l->append(StringPrintf("(%d %d)", p.success, p.input_buffer_size));
+ l->append(base::StringPrintf("(%d %d)", p.success, p.input_buffer_size));
}
///////////////////////////////////////////////////////////////////////////////
@@ -74,9 +74,9 @@ bool ParamTraits<GpuVideoDecoderInputBufferParam>::Read(
void ParamTraits<GpuVideoDecoderInputBufferParam>::Log(
const GpuVideoDecoderInputBufferParam& p, std::string* l) {
- l->append(StringPrintf("(%d %d %d)",
- static_cast<int>(p.timestamp),
- p.offset, p.size));
+ l->append(base::StringPrintf("(%d %d %d)",
+ static_cast<int>(p.timestamp),
+ p.offset, p.size));
}
///////////////////////////////////////////////////////////////////////////////
@@ -95,7 +95,7 @@ bool ParamTraits<GpuVideoDecoderErrorInfoParam>::Read(
void ParamTraits<GpuVideoDecoderErrorInfoParam>::Log(
const GpuVideoDecoderErrorInfoParam& p, std::string* l) {
- l->append(StringPrintf("(%d)", p.error_id));
+ l->append(base::StringPrintf("(%d)", p.error_id));
}
///////////////////////////////////////////////////////////////////////////////
@@ -114,7 +114,7 @@ bool ParamTraits<GpuVideoDecoderFormatChangeParam>::Read(
void ParamTraits<GpuVideoDecoderFormatChangeParam>::Log(
const GpuVideoDecoderFormatChangeParam& p, std::string* l) {
- l->append(StringPrintf("%d", p.input_buffer_size));
+ l->append(base::StringPrintf("%d", p.input_buffer_size));
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/common/important_file_writer.cc b/chrome/common/important_file_writer.cc
index 2d9503d..94a8e57 100644
--- a/chrome/common/important_file_writer.cc
+++ b/chrome/common/important_file_writer.cc
@@ -6,7 +6,6 @@
#include <stdio.h>
-#include <ostream>
#include <string>
#include "base/file_path.h"
@@ -46,28 +45,28 @@ class WriteToDiskTask : public Task {
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");
+ file_util::Delete(tmp_file_path, false);
return;
}
if (bytes_written < data_.length()) {
- file_util::Delete(tmp_file_path, false);
LogFailure("error writing, bytes_written=" +
base::Uint64ToString(bytes_written));
+ file_util::Delete(tmp_file_path, false);
return;
}
if (!file_util::ReplaceFile(tmp_file_path, path_)) {
- file_util::Delete(tmp_file_path, false);
LogFailure("could not rename temporary file");
+ file_util::Delete(tmp_file_path, false);
return;
}
}
private:
void LogFailure(const std::string& message) {
- LOG(WARNING) << "failed to write " << path_.value()
- << ": " << message;
+ PLOG(WARNING) << "failed to write " << path_.value()
+ << ": " << message;
}
const FilePath path_;
diff --git a/chrome/common/json_pref_store.h b/chrome/common/json_pref_store.h
index 5211889..0407d1e 100644
--- a/chrome/common/json_pref_store.h
+++ b/chrome/common/json_pref_store.h
@@ -31,7 +31,7 @@ class JsonPrefStore : public PrefStore,
// PrefStore methods:
virtual bool ReadOnly() { return read_only_; }
- virtual DictionaryValue* prefs() { return prefs_.get(); }
+ virtual DictionaryValue* prefs() const { return prefs_.get(); }
virtual PrefReadError ReadPrefs();
diff --git a/chrome/common/libxml_utils.cc b/chrome/common/libxml_utils.cc
index f06df72..009f0d3 100644
--- a/chrome/common/libxml_utils.cc
+++ b/chrome/common/libxml_utils.cc
@@ -6,7 +6,7 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
-#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "libxml/xmlreader.h"
@@ -35,7 +35,7 @@ void XmlReader::GenericErrorCallback(void* context, const char* msg, ...) {
va_start(args, msg);
XmlReader* reader = static_cast<XmlReader*>(context);
- reader->errors_.append(StringPrintV(msg, args));
+ reader->errors_.append(base::StringPrintV(msg, args));
va_end(args);
}
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
index beab5b8..196c581 100644
--- a/chrome/common/logging_chrome.cc
+++ b/chrome/common/logging_chrome.cc
@@ -32,7 +32,7 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
-#include "base/debug_util.h"
+#include "base/debug/debugger.h"
#include "base/environment.h"
#include "base/file_path.h"
#include "base/file_util.h"
@@ -64,8 +64,9 @@ static bool chrome_logging_redirected_ = false;
#if defined(OS_WIN)
// {7FE69228-633E-4f06-80C1-527FEA23E3A7}
-DEFINE_GUID(kChromeTraceProviderName,
- 0x7fe69228, 0x633e, 0x4f06, 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7);
+static const GUID kChromeTraceProviderName = {
+ 0x7fe69228, 0x633e, 0x4f06,
+ { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } };
#endif
// Assertion handler for logging errors that occur when dialogs are
@@ -73,7 +74,7 @@ DEFINE_GUID(kChromeTraceProviderName,
// with that error in the str parameter.
MSVC_DISABLE_OPTIMIZE();
static void SilentRuntimeAssertHandler(const std::string& str) {
- DebugUtil::BreakDebugger();
+ base::debug::BreakDebugger();
}
static void SilentRuntimeReportHandler(const std::string& str) {
}
@@ -135,47 +136,106 @@ LoggingDestination DetermineLogMode(const CommandLine& command_line) {
}
#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();
+namespace {
+FilePath GenerateTimestampedName(const FilePath& base_path,
+ base::Time timestamp) {
+ base::Time::Exploded time_deets;
+ timestamp.LocalExplode(&time_deets);
+ std::string suffix = base::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);
+ return base_path.InsertBeforeExtension(suffix);
+}
+
+FilePath SetUpSymlinkIfNeeded(const FilePath& symlink_path, bool new_log) {
+ DCHECK(!symlink_path.empty());
+
+ // If not starting a new log, then just log through the existing
+ // symlink, but if the symlink doesn't exist, create it. If
+ // starting a new log, then delete the old symlink and make a new
+ // one to a fresh log file.
+ FilePath target_path;
+ bool symlink_exists = file_util::PathExists(symlink_path);
+ if (new_log || !symlink_exists) {
+ target_path = GenerateTimestampedName(symlink_path, base::Time::Now());
+
+ // We don't care if the unlink fails; we're going to continue anyway.
+ if (unlink(symlink_path.value().c_str()) == -1) {
+ if (symlink_exists) // only warn if we might expect it to succeed.
+ PLOG(WARNING) << "Unable to unlink " << symlink_path.value();
+ }
+ if (symlink(target_path.value().c_str(),
+ symlink_path.value().c_str()) == -1) {
+ PLOG(ERROR) << "Unable to create symlink " << symlink_path.value()
+ << " pointing at " << target_path.value();
+ }
+ } else {
+ char buf[PATH_MAX];
+ ssize_t count = readlink(symlink_path.value().c_str(), buf, arraysize(buf));
+ if (count > 0) {
+ target_path = FilePath(FilePath::StringType(buf, count));
+ } else {
+ PLOG(ERROR) << "Unable to read symlink " << symlink_path.value();
+ }
}
+ return target_path;
}
-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 RemoveSymlinkAndLog(const FilePath& link_path,
+ const FilePath& target_path) {
+ if (::unlink(link_path.value().c_str()) == -1)
+ PLOG(WARNING) << "Unable to unlink symlink " << link_path.value();
+ if (::unlink(target_path.value().c_str()) == -1)
+ PLOG(WARNING) << "Unable to unlink log file " << target_path.value();
}
-void RedirectChromeLogging(const FilePath& new_log_dir,
- const CommandLine& command_line,
- OldFileDeletionState delete_old_log_file) {
+} // anonymous namespace
+
+FilePath GetSessionLogFile(const CommandLine& command_line) {
+ FilePath log_dir;
+ std::string log_dir_str;
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ if (env->GetVar(env_vars::kSessionLogDir, &log_dir_str) &&
+ !log_dir_str.empty()) {
+ log_dir = FilePath(log_dir_str);
+ } else {
+ PathService::Get(chrome::DIR_USER_DATA, &log_dir);
+ FilePath login_profile =
+ command_line.GetSwitchValuePath(switches::kLoginProfile);
+ log_dir = log_dir.Append(login_profile);
+ }
+ return log_dir.Append(GetLogFileName().BaseName());
+}
+
+void RedirectChromeLogging(const CommandLine& command_line) {
DCHECK(!chrome_logging_redirected_) <<
"Attempted to redirect logging when it was already initialized.";
- 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);
- chrome_logging_redirected_ = true;
+
+ // Redirect logs to the session log directory, if set. Otherwise
+ // defaults to the profile dir.
+ FilePath log_path = GetSessionLogFile(command_line);
+
+ // Always force a new symlink when redirecting.
+ FilePath target_path = SetUpSymlinkIfNeeded(log_path, true);
+
+ // ChromeOS always logs through the symlink, so it shouldn't be
+ // deleted if it already exists.
+ if (!InitLogging(log_path.value().c_str(),
+ DetermineLogMode(command_line),
+ logging::LOCK_LOG_FILE,
+ logging::APPEND_TO_OLD_LOG_FILE)) {
+ LOG(ERROR) << "Unable to initialize logging to " << log_path.value();
+ RemoveSymlinkAndLog(log_path, target_path);
+ } else {
+ chrome_logging_redirected_ = true;
+ }
}
+
+
#endif
void InitChromeLogging(const CommandLine& command_line,
@@ -188,21 +248,54 @@ void InitChromeLogging(const CommandLine& command_line,
#endif
FilePath log_path = GetLogFileName();
+
#if defined(OS_CHROMEOS)
- log_path = TimestampLog(log_path, base::Time::Now());
+ // For BWSI (Incognito) logins, we want to put the logs in the user
+ // profile directory that is created for the temporary session instead
+ // of in the system log directory, for privacy reasons.
+ if (command_line.HasSwitch(switches::kGuestSession))
+ log_path = GetSessionLogFile(command_line);
+
+ // On ChromeOS we log to the symlink. We force creation of a new
+ // symlink if we've been asked to delete the old log, since that
+ // indicates the start of a new session.
+ FilePath target_path = SetUpSymlinkIfNeeded(
+ log_path, delete_old_log_file == logging::DELETE_OLD_LOG_FILE);
+
+ // Because ChromeOS manages the move to a new session by redirecting
+ // the link, it shouldn't remove the old file in the logging code,
+ // since that will remove the newly created link instead.
+ delete_old_log_file = logging::APPEND_TO_OLD_LOG_FILE;
#endif
- logging::InitLogging(log_path.value().c_str(),
- DetermineLogMode(command_line),
- logging::LOCK_LOG_FILE,
- delete_old_log_file);
+ bool success = InitLogging(log_path.value().c_str(),
+ DetermineLogMode(command_line),
+ logging::LOCK_LOG_FILE,
+ delete_old_log_file);
+
+#if defined(OS_CHROMEOS)
+ if (!success) {
+ PLOG(ERROR) << "Unable to initialize logging to " << log_path.value()
+ << " (which should be a link to " << target_path.value() << ")";
+ RemoveSymlinkAndLog(log_path, target_path);
+ return;
+ }
+#else
+ if (!success) {
+ PLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
+ return;
+ }
+#endif
// Default to showing error dialogs.
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoErrorDialogs))
logging::SetShowErrorDialogs(true);
// we want process and thread IDs because we have a lot of things running
- logging::SetLogItems(true, true, false, true);
+ logging::SetLogItems(true, // enable_process_id
+ true, // enable_thread_id
+ false, // enable_timestamp
+ true); // enable_tickcount
// We call running in unattended mode "headless", and allow
// headless mode to be configured either by the Environment
diff --git a/chrome/common/logging_chrome.h b/chrome/common/logging_chrome.h
index a2d62d5..6fc1389 100644
--- a/chrome/common/logging_chrome.h
+++ b/chrome/common/logging_chrome.h
@@ -37,9 +37,11 @@ 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);
+// Get the log file location.
+FilePath GetSessionLogFile(const CommandLine& command_line);
+
+// Redirects chrome logging to the appropriate session log dir.
+void RedirectChromeLogging(const CommandLine& command_line);
#endif
// Call when done using logging for Chrome.
diff --git a/chrome/common/logging_chrome_uitest.cc b/chrome/common/logging_chrome_uitest.cc
index 0dc44d9..96e3205 100644
--- a/chrome/common/logging_chrome_uitest.cc
+++ b/chrome/common/logging_chrome_uitest.cc
@@ -162,10 +162,7 @@ class RendererCrashTest : public UITest {
#define EXPECTED_CRASH_CRASHES 1
#endif
-#if defined(OS_WIN)
-// http://crbug.com/32048
-#define Crash FLAKY_Crash
-#elif defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS)
// http://crbug.com/43115
#define Crash DISABLED_Crash
#elif defined(OS_MACOSX)
diff --git a/chrome/common/metrics_helpers.cc b/chrome/common/metrics_helpers.cc
index 6dd0a42..e25355c 100644
--- a/chrome/common/metrics_helpers.cc
+++ b/chrome/common/metrics_helpers.cc
@@ -484,9 +484,25 @@ 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();
+ int corruption = histogram.FindCorruption(snapshot);
+ if (corruption) {
+ NOTREACHED();
+ // Don't send corrupt data to metrics survices.
+ UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesBrowser",
+ corruption, Histogram::NEVER_EXCEEDED_VALUE);
+ typedef std::map<std::string, int> ProblemMap;
+ static ProblemMap* inconsistencies = new ProblemMap;
+ int old_corruption = (*inconsistencies)[histogram_name];
+ if (old_corruption == (corruption | old_corruption))
+ return; // We've already seen this corruption for this histogram.
+ (*inconsistencies)[histogram_name] |= corruption;
+ UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesBrowserUnique",
+ corruption, Histogram::NEVER_EXCEEDED_VALUE);
+ return;
+ }
+
// Find the already sent stats, or create an empty set.
LoggedSampleMap::iterator it = logged_samples_.find(histogram_name);
Histogram::SampleSet* already_logged;
diff --git a/chrome/common/net/gaia/gaia_authenticator2.cc b/chrome/common/net/gaia/gaia_authenticator2.cc
index 108d76c..21b8190 100644
--- a/chrome/common/net/gaia/gaia_authenticator2.cc
+++ b/chrome/common/net/gaia/gaia_authenticator2.cc
@@ -11,6 +11,7 @@
#include "base/string_split.h"
#include "base/string_util.h"
#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/net/gaia/google_service_auth_error.h"
#include "chrome/common/net/http_return.h"
#include "chrome/common/net/url_request_context_getter.h"
@@ -42,7 +43,7 @@ const char GaiaAuthenticator2::kIssueAuthTokenFormat[] =
"SID=%s&"
"LSID=%s&"
"service=%s&"
- "Session=true";
+ "Session=%s";
// static
const char GaiaAuthenticator2::kGetUserInfoFormat[] =
"LSID=%s";
@@ -149,24 +150,24 @@ std::string GaiaAuthenticator2::MakeClientLoginBody(
kAccountTypeGoogle;
if (login_token.empty() || login_captcha.empty()) {
- return StringPrintf(kClientLoginFormat,
- encoded_username.c_str(),
- encoded_password.c_str(),
- kCookiePersistence,
- account_type,
- source.c_str(),
- service);
+ return base::StringPrintf(kClientLoginFormat,
+ encoded_username.c_str(),
+ encoded_password.c_str(),
+ kCookiePersistence,
+ account_type,
+ source.c_str(),
+ service);
}
- return StringPrintf(kClientLoginCaptchaFormat,
- encoded_username.c_str(),
- encoded_password.c_str(),
- kCookiePersistence,
- account_type,
- source.c_str(),
- service,
- encoded_login_token.c_str(),
- encoded_login_captcha.c_str());
+ return base::StringPrintf(kClientLoginCaptchaFormat,
+ encoded_username.c_str(),
+ encoded_password.c_str(),
+ kCookiePersistence,
+ account_type,
+ source.c_str(),
+ service,
+ encoded_login_token.c_str(),
+ encoded_login_captcha.c_str());
}
@@ -178,16 +179,22 @@ std::string GaiaAuthenticator2::MakeIssueAuthTokenBody(
std::string encoded_sid = UrlEncodeString(sid);
std::string encoded_lsid = UrlEncodeString(lsid);
- return StringPrintf(kIssueAuthTokenFormat,
- encoded_sid.c_str(),
- encoded_lsid.c_str(),
- service);
+ // All tokens should be session tokens except the gaia auth token.
+ bool session = true;
+ if (!strcmp(service, GaiaConstants::kGaiaService))
+ session = false;
+
+ return base::StringPrintf(kIssueAuthTokenFormat,
+ encoded_sid.c_str(),
+ encoded_lsid.c_str(),
+ service,
+ session ? "true" : "false");
}
// static
std::string GaiaAuthenticator2::MakeGetUserInfoBody(const std::string& lsid) {
std::string encoded_lsid = UrlEncodeString(lsid);
- return StringPrintf(kGetUserInfoFormat, encoded_lsid.c_str());
+ return base::StringPrintf(kGetUserInfoFormat, encoded_lsid.c_str());
}
// Helper method that extracts tokens from a successful reply.
diff --git a/chrome/common/net/gaia/gaia_authenticator2_unittest.cc b/chrome/common/net/gaia/gaia_authenticator2_unittest.cc
index 44d1a17..6ef0a51 100644
--- a/chrome/common/net/gaia/gaia_authenticator2_unittest.cc
+++ b/chrome/common/net/gaia/gaia_authenticator2_unittest.cc
@@ -245,8 +245,8 @@ TEST_F(GaiaAuthenticator2Test, WorkingIssueAuthToken) {
TEST_F(GaiaAuthenticator2Test, CheckTwoFactorResponse) {
std::string response =
- StringPrintf("Error=BadAuthentication\n%s\n",
- GaiaAuthenticator2::kSecondFactor);
+ base::StringPrintf("Error=BadAuthentication\n%s\n",
+ GaiaAuthenticator2::kSecondFactor);
EXPECT_TRUE(GaiaAuthenticator2::IsSecondFactorSuccess(response));
}
@@ -256,7 +256,7 @@ TEST_F(GaiaAuthenticator2Test, CheckNormalErrorCode) {
}
TEST_F(GaiaAuthenticator2Test, TwoFactorLogin) {
- std::string response = StringPrintf("Error=BadAuthentication\n%s\n",
+ std::string response = base::StringPrintf("Error=BadAuthentication\n%s\n",
GaiaAuthenticator2::kSecondFactor);
GoogleServiceAuthError error =
diff --git a/chrome/common/net/gaia/gaia_constants.cc b/chrome/common/net/gaia/gaia_constants.cc
index 810055e..addd468 100644
--- a/chrome/common/net/gaia/gaia_constants.cc
+++ b/chrome/common/net/gaia/gaia_constants.cc
@@ -12,6 +12,8 @@ namespace GaiaConstants {
const char kChromeOSSource[] = "chromeos";
const char kChromeSource[] = "ChromiumBrowser";
+// Service name for Gaia. Used to convert to cookie auth.
+const char kGaiaService[] = "gaia";
// Service name for Gaia Contacts API. API is used to get user's image.
const char kContactsService[] = "cp";
// Service name for sync.
@@ -22,5 +24,7 @@ const char kTalkService[] = "talk";
const char kRemotingService[] = "chromoting";
// Service name for cloud print.
const char kCloudPrintService[] = "cloudprint";
+// Service name for device management (cloud-based policy) server.
+const char kDeviceManagementService[] = "mobilesync";
} // namespace GaiaConstants
diff --git a/chrome/common/net/gaia/gaia_constants.h b/chrome/common/net/gaia/gaia_constants.h
index b1a2617..d0f3b10 100644
--- a/chrome/common/net/gaia/gaia_constants.h
+++ b/chrome/common/net/gaia/gaia_constants.h
@@ -14,11 +14,13 @@ extern const char kChromeOSSource[];
extern const char kChromeSource[];
// Gaia services for requesting
+extern const char kGaiaService[]; // uber token
extern const char kContactsService[];
extern const char kTalkService[];
extern const char kSyncService[];
extern const char kRemotingService[];
extern const char kCloudPrintService[];
+extern const char kDeviceManagementService[];
} // namespace GaiaConstants
diff --git a/chrome/common/net/gaia/google_service_auth_error.h b/chrome/common/net/gaia/google_service_auth_error.h
index fa6f76b..032f59f 100644
--- a/chrome/common/net/gaia/google_service_auth_error.h
+++ b/chrome/common/net/gaia/google_service_auth_error.h
@@ -71,6 +71,10 @@ class GoogleServiceAuthError {
// The requestor of the authentication step cancelled the request
// prior to completion.
REQUEST_CANCELED = 9,
+
+ // The user has provided a HOSTED account, when this service requires
+ // a GOOGLE account.
+ HOSTED_NOT_ALLOWED = 10,
};
// Additional data for CAPTCHA_REQUIRED errors.
diff --git a/chrome/common/net/raw_host_resolver_proc.cc b/chrome/common/net/raw_host_resolver_proc.cc
new file mode 100644
index 0000000..474afa2
--- /dev/null
+++ b/chrome/common/net/raw_host_resolver_proc.cc
@@ -0,0 +1,28 @@
+// 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/raw_host_resolver_proc.h"
+
+#include "base/logging.h"
+#include "net/base/net_errors.h"
+
+namespace chrome_common_net {
+
+RawHostResolverProc::RawHostResolverProc(const net::IPAddressNumber& dns_server,
+ net::HostResolverProc* previous)
+ : HostResolverProc(previous), dns_server_(dns_server) {}
+
+int RawHostResolverProc::Resolve(const std::string& host,
+ net::AddressFamily address_family,
+ net::HostResolverFlags host_resolver_flags,
+ net::AddressList* addrlist,
+ int* os_error) {
+ // TODO(agayev): Implement raw DNS resolution.
+ LOG(INFO) << "trying to resolve " << host;
+ return net::ERR_NAME_NOT_RESOLVED;
+}
+
+RawHostResolverProc::~RawHostResolverProc() {}
+
+} // namespace chrome_common_net
diff --git a/chrome/common/net/raw_host_resolver_proc.h b/chrome/common/net/raw_host_resolver_proc.h
new file mode 100644
index 0000000..7ec751a
--- /dev/null
+++ b/chrome/common/net/raw_host_resolver_proc.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_NET_RAW_HOST_RESOLVER_PROC_H_
+#define CHROME_COMMON_NET_RAW_HOST_RESOLVER_PROC_H_
+#pragma once
+
+// RawHostResolverProc will eventually be a getaddrinfo() replacement. It
+// will construct and send DNS queries to the DNS server specified via
+// --dns-server flag and will parse the responses and put it into a cache
+// together with the TTL. Necessary amendments will be made to cache and
+// HostResolverProc interface to accomodate these.
+
+#include <string>
+
+#include "net/base/host_resolver_proc.h"
+#include "net/base/net_util.h"
+
+namespace chrome_common_net {
+
+class RawHostResolverProc : public net::HostResolverProc {
+ public:
+ RawHostResolverProc(const net::IPAddressNumber& dns_server,
+ net::HostResolverProc* previous);
+
+ virtual int Resolve(const std::string& host,
+ net::AddressFamily address_family,
+ net::HostResolverFlags host_resolver_flags,
+ net::AddressList* addrlist,
+ int* os_error);
+ private:
+ virtual ~RawHostResolverProc();
+
+ net::IPAddressNumber dns_server_;
+};
+
+} // namespace chrome_common_net
+
+#endif // CHROME_COMMON_NET_RAW_HOST_RESOLVER_PROC_H_
diff --git a/chrome/common/net/test_url_fetcher_factory.cc b/chrome/common/net/test_url_fetcher_factory.cc
index 6ab3a49..635319f 100644
--- a/chrome/common/net/test_url_fetcher_factory.cc
+++ b/chrome/common/net/test_url_fetcher_factory.cc
@@ -1,13 +1,15 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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/test_url_fetcher_factory.h"
-TestURLFetcher::TestURLFetcher(const GURL& url,
+TestURLFetcher::TestURLFetcher(int id,
+ const GURL& url,
URLFetcher::RequestType request_type,
URLFetcher::Delegate* d)
: URLFetcher(url, request_type, d),
+ id_(id),
original_url_(url) {
}
@@ -16,7 +18,7 @@ URLFetcher* TestURLFetcherFactory::CreateURLFetcher(
const GURL& url,
URLFetcher::RequestType request_type,
URLFetcher::Delegate* d) {
- TestURLFetcher* fetcher = new TestURLFetcher(url, request_type, d);
+ TestURLFetcher* fetcher = new TestURLFetcher(id, url, request_type, d);
fetchers_[id] = fetcher;
return fetcher;
}
@@ -25,3 +27,9 @@ TestURLFetcher* TestURLFetcherFactory::GetFetcherByID(int id) const {
Fetchers::const_iterator i = fetchers_.find(id);
return i == fetchers_.end() ? NULL : i->second;
}
+
+void TestURLFetcherFactory::RemoveFetcherFromMap(int id) {
+ Fetchers::iterator i = fetchers_.find(id);
+ DCHECK(i != fetchers_.end());
+ fetchers_.erase(i);
+}
diff --git a/chrome/common/net/test_url_fetcher_factory.h b/chrome/common/net/test_url_fetcher_factory.h
index a831e3a..3afa19e 100644
--- a/chrome/common/net/test_url_fetcher_factory.h
+++ b/chrome/common/net/test_url_fetcher_factory.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -39,14 +39,17 @@
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(); }
+ TestURLFetcher(int id,
+ const GURL& url,
+ RequestType request_type,
+ Delegate* d);
// Overriden to do nothing. It is assumed the caller will notify the delegate.
virtual void Start() {}
+ // Unique ID in our factory.
+ int id() const { return id_; }
+
// 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.
@@ -55,7 +58,11 @@ class TestURLFetcher : public URLFetcher {
// Returns the data uploaded on this URLFetcher.
const std::string& upload_data() const { return URLFetcher::upload_data(); }
+ // Returns the delegate installed on the URLFetcher.
+ Delegate* delegate() const { return URLFetcher::delegate(); }
+
private:
+ const int id_;
const GURL original_url_;
DISALLOW_COPY_AND_ASSIGN(TestURLFetcher);
@@ -71,8 +78,8 @@ class TestURLFetcherFactory : public URLFetcher::Factory {
const GURL& url,
URLFetcher::RequestType request_type,
URLFetcher::Delegate* d);
-
TestURLFetcher* GetFetcherByID(int id) const;
+ void RemoveFetcherFromMap(int id);
private:
// Maps from id passed to create to the returned URLFetcher.
diff --git a/chrome/common/net/url_fetcher.cc b/chrome/common/net/url_fetcher.cc
index 4bfd8c7..9551255 100644
--- a/chrome/common/net/url_fetcher.cc
+++ b/chrome/common/net/url_fetcher.cc
@@ -34,7 +34,6 @@ 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
@@ -58,10 +57,6 @@ class URLFetcher::Core
// 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);
@@ -244,13 +239,6 @@ void URLFetcher::Core::Stop() {
}
}
-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::CancelAll() {
g_registry.Get().CancelAll();
}
@@ -308,7 +296,6 @@ void URLFetcher::Core::StartURLRequest() {
CHECK(request_context_getter_);
DCHECK(!request_.get());
- MessageLoop::current()->AddDestructionObserver(this);
g_registry.Get().AddURLFetcherCore(this);
request_.reset(new URLRequest(original_url_, this));
int flags = request_->load_flags() | load_flags_;
@@ -401,7 +388,6 @@ void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
void URLFetcher::Core::ReleaseRequest() {
request_.reset();
g_registry.Get().RemoveURLFetcherCore(this);
- MessageLoop::current()->RemoveDestructionObserver(this);
}
void URLFetcher::set_upload_data(const std::string& upload_content_type,
diff --git a/chrome/common/net/url_fetcher_unittest.cc b/chrome/common/net/url_fetcher_unittest.cc
index 3fc8469..466d8e6 100644
--- a/chrome/common/net/url_fetcher_unittest.cc
+++ b/chrome/common/net/url_fetcher_unittest.cc
@@ -5,6 +5,7 @@
#include "base/message_loop_proxy.h"
#include "base/thread.h"
#include "base/waitable_event.h"
+#include "build/build_config.h"
#include "chrome/common/chrome_plugin_lib.h"
#include "chrome/common/net/url_fetcher.h"
#include "chrome/common/net/url_fetcher_protect.h"
@@ -14,6 +15,10 @@
#include "net/test/test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_LINUX)
+#include "net/ocsp/nss_ocsp.h"
+#endif
+
using base::Time;
using base::TimeDelta;
@@ -34,7 +39,7 @@ class TestURLRequestContextGetter : public URLRequestContextGetter {
context_ = new TestURLRequestContext();
return context_;
}
- virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() {
+ virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const {
return io_message_loop_proxy_;
}
@@ -74,6 +79,15 @@ class URLFetcherTest : public testing::Test, public URLFetcher::Delegate {
// Ensure that any plugin operations done by other tests are cleaned up.
ChromePluginLib::UnloadAllPlugins();
+#if defined(OS_LINUX)
+ net::EnsureOCSPInit();
+#endif
+ }
+
+ virtual void TearDown() {
+#if defined(OS_LINUX)
+ net::ShutdownOCSP();
+#endif
}
// URLFetcher is designed to run on the main UI thread, but in our tests
@@ -199,7 +213,7 @@ class CancelTestURLRequestContextGetter : public URLRequestContextGetter {
}
return context_;
}
- virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() {
+ virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const {
return io_message_loop_proxy_;
}
void WaitForContextCreation() {
@@ -540,8 +554,9 @@ TEST_F(URLFetcherProtectTestPassedThrough, ServerUnavailablePropagateResponse) {
TEST_F(URLFetcherBadHTTPSTest, BadHTTPSTest) {
- net::TestServer test_server(net::TestServer::TYPE_HTTPS_EXPIRED_CERTIFICATE,
- FilePath(kDocRoot));
+ net::TestServer::HTTPSOptions https_options(
+ net::TestServer::HTTPSOptions::CERT_EXPIRED);
+ net::TestServer test_server(https_options, FilePath(kDocRoot));
ASSERT_TRUE(test_server.Start());
CreateFetcher(test_server.GetURL("defaultresponse"));
diff --git a/chrome/common/net/url_request_context_getter.cc b/chrome/common/net/url_request_context_getter.cc
index 57feb0e..08b5368 100644
--- a/chrome/common/net/url_request_context_getter.cc
+++ b/chrome/common/net/url_request_context_getter.cc
@@ -14,7 +14,7 @@ URLRequestContextGetter::URLRequestContextGetter() : is_main_(false) {}
URLRequestContextGetter::~URLRequestContextGetter() {}
-void URLRequestContextGetter::OnDestruct() {
+void URLRequestContextGetter::OnDestruct() const {
scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy =
GetIOMessageLoopProxy();
DCHECK(io_message_loop_proxy);
diff --git a/chrome/common/net/url_request_context_getter.h b/chrome/common/net/url_request_context_getter.h
index 2b6ea82..ade5e1a 100644
--- a/chrome/common/net/url_request_context_getter.h
+++ b/chrome/common/net/url_request_context_getter.h
@@ -33,7 +33,8 @@ class URLRequestContextGetter
// 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;
+ virtual scoped_refptr<base::MessageLoopProxy>
+ GetIOMessageLoopProxy() const = 0;
// Controls whether or not the URLRequestContextGetter considers itself to be
// the the "main" URLRequestContextGetter. Note that each Profile will have a
@@ -44,7 +45,7 @@ class URLRequestContextGetter
void set_is_main(bool is_main) { is_main_ = is_main; }
protected:
- friend class DeleteTask<URLRequestContextGetter>;
+ friend class DeleteTask<const URLRequestContextGetter>;
friend struct URLRequestContextGetterTraits;
URLRequestContextGetter();
@@ -55,7 +56,7 @@ class URLRequestContextGetter
private:
// OnDestruct is meant to ensure deletion on the thread on which the request
// IO happens.
- void OnDestruct();
+ void OnDestruct() const;
// Indicates whether or not this is the default URLRequestContextGetter for
// the main Profile.
@@ -63,7 +64,7 @@ class URLRequestContextGetter
};
struct URLRequestContextGetterTraits {
- static void Destruct(URLRequestContextGetter* context_getter) {
+ static void Destruct(const URLRequestContextGetter* context_getter) {
context_getter->OnDestruct();
}
};
diff --git a/chrome/common/net/x509_certificate_model.cc b/chrome/common/net/x509_certificate_model.cc
index 5f39685..0ec2bff 100644
--- a/chrome/common/net/x509_certificate_model.cc
+++ b/chrome/common/net/x509_certificate_model.cc
@@ -49,5 +49,41 @@ std::string ProcessIDN(const std::string& input) {
input16, output16);
}
+std::string ProcessRawBytesWithSeparators(const unsigned char* data,
+ size_t data_length,
+ char hex_separator,
+ char line_separator) {
+ static const char kHexChars[] = "0123456789ABCDEF";
+
+ // Each input byte creates two output hex characters + a space or newline,
+ // except for the last byte.
+ std::string ret;
+ size_t kMin = 0U;
+ ret.reserve(std::max(kMin, data_length * 3 - 1));
+
+ for (size_t i = 0; i < data_length; ++i) {
+ unsigned char b = data[i];
+ ret.push_back(kHexChars[(b >> 4) & 0xf]);
+ ret.push_back(kHexChars[b & 0xf]);
+ if (i + 1 < data_length) {
+ if ((i + 1) % 16 == 0)
+ ret.push_back(line_separator);
+ else
+ ret.push_back(hex_separator);
+ }
+ }
+ return ret;
+}
+
+std::string ProcessRawBytes(const unsigned char* data, size_t data_length) {
+ return ProcessRawBytesWithSeparators(data, data_length, ' ', '\n');
+}
+
+#if defined(USE_NSS)
+std::string ProcessRawBits(const unsigned char* data, size_t data_length) {
+ return ProcessRawBytes(data, (data_length + 7) / 8);
+}
+#endif // USE_NSS
+
} // x509_certificate_model
diff --git a/chrome/common/net/x509_certificate_model.h b/chrome/common/net/x509_certificate_model.h
index 351f489..3e4f14f 100644
--- a/chrome/common/net/x509_certificate_model.h
+++ b/chrome/common/net/x509_certificate_model.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_BASE_X509_CERTIFICATE_MODEL_H_
-#define NET_BASE_X509_CERTIFICATE_MODEL_H_
+#ifndef CHROME_COMMON_NET_X509_CERTIFICATE_MODEL_H_
+#define CHROME_COMMON_NET_X509_CERTIFICATE_MODEL_H_
#pragma once
#include "net/base/cert_database.h"
@@ -123,6 +123,24 @@ std::string ProcessRawBitsSignatureWrap(
void RegisterDynamicOids();
+// Format a buffer as |hex_separator| separated string, with 16 bytes on each
+// line separated using |line_separator|.
+std::string ProcessRawBytesWithSeparators(const unsigned char* data,
+ size_t data_length,
+ char hex_separator,
+ char line_separator);
+
+// Format a buffer as a space separated string, with 16 bytes on each line.
+std::string ProcessRawBytes(const unsigned char* data,
+ size_t data_length);
+
+#if defined(USE_NSS)
+// Format a buffer as a space separated string, with 16 bytes on each line.
+// |data_length| is the length in bits.
+std::string ProcessRawBits(const unsigned char* data,
+ size_t data_length);
+#endif // USE_NSS
+
} // namespace x509_certificate_model
-#endif // NET_BASE_X509_CERTIFICATE_MODEL_H_
+#endif // CHROME_COMMON_NET_X509_CERTIFICATE_MODEL_H_
diff --git a/chrome/common/net/x509_certificate_model_nss.cc b/chrome/common/net/x509_certificate_model_nss.cc
index da17a60..4d46174 100644
--- a/chrome/common/net/x509_certificate_model_nss.cc
+++ b/chrome/common/net/x509_certificate_model_nss.cc
@@ -42,7 +42,6 @@ std::string Stringize(char* nss_text, const std::string& alternative_text) {
// algorithm, but given the limited uses, not worth fixing.)
std::string HashCert(CERTCertificate* cert, HASH_HashType algorithm, int len) {
unsigned char fingerprint[HASH_LENGTH_MAX];
- SECItem fingerprint_item;
DCHECK(NULL != cert->derCert.data);
DCHECK_NE(0U, cert->derCert.len);
@@ -51,9 +50,7 @@ std::string HashCert(CERTCertificate* cert, HASH_HashType algorithm, int len) {
SECStatus rv = HASH_HashBuf(algorithm, fingerprint, cert->derCert.data,
cert->derCert.len);
DCHECK_EQ(rv, SECSuccess);
- fingerprint_item.data = fingerprint;
- fingerprint_item.len = len;
- return psm::ProcessRawBytes(&fingerprint_item);
+ return x509_certificate_model::ProcessRawBytes(fingerprint, len);
}
std::string ProcessSecAlgorithmInternal(SECAlgorithmID* algorithm_id) {
@@ -293,6 +290,7 @@ void DestroyCertChain(X509Certificate::OSCertHandles* cert_handles) {
for (X509Certificate::OSCertHandles::iterator i(cert_handles->begin());
i != cert_handles->end(); ++i)
CERT_DestroyCertificate(*i);
+ cert_handles->clear();
}
string GetDerString(X509Certificate::OSCertHandle cert_handle) {
@@ -372,7 +370,8 @@ string ProcessSubjectPublicKeyInfo(X509Certificate::OSCertHandle cert_handle) {
}
string ProcessRawBitsSignatureWrap(X509Certificate::OSCertHandle cert_handle) {
- return psm::ProcessRawBits(&cert_handle->signatureWrap.signature);
+ return ProcessRawBits(cert_handle->signatureWrap.signature.data,
+ cert_handle->signatureWrap.signature.len);
}
void RegisterDynamicOids() {
diff --git a/chrome/common/net/x509_certificate_model_openssl.cc b/chrome/common/net/x509_certificate_model_openssl.cc
index 57670f1..7c4836f 100644
--- a/chrome/common/net/x509_certificate_model_openssl.cc
+++ b/chrome/common/net/x509_certificate_model_openssl.cc
@@ -2,11 +2,42 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/common/net/x509_certificate_model.h"
+
+#include <openssl/obj_mac.h>
+#include <openssl/sha.h>
#include <openssl/x509v3.h>
-#include "chrome/common/net/x509_certificate_model.h"
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "net/base/x509_openssl_util.h"
+
+namespace nxou = net::x509_openssl_util;
+
+namespace {
+
+std::string AlternativeWhenEmpty(const std::string& text,
+ const std::string& alternative) {
+ return text.empty() ? alternative : text;
+}
+
+std::string GetKeyValuesFromName(X509_NAME* name) {
+ std::string ret;
+ int rdns = X509_NAME_entry_count(name) - 1;
+ for (int i = rdns; i >= 0; --i) {
+ std::string key;
+ std::string value;
+ if (!nxou::ParsePrincipalKeyAndValueByIndex(name, i, &key, &value))
+ break;
+ ret += key;
+ ret += " = ";
+ ret += value;
+ ret += '\n';
+ }
+ return ret;
+}
-#include "net/base/x509_certificate.h"
+} // namepsace
namespace x509_certificate_model {
@@ -23,7 +54,9 @@ std::string GetTokenName(X509Certificate::OSCertHandle cert_handle) {
}
std::string GetVersion(net::X509Certificate::OSCertHandle cert_handle) {
- // TODO(bulach): implement me.
+ unsigned long version = X509_get_version(cert_handle);
+ if (version != ULONG_MAX)
+ return base::UintToString(version + 1);
return "";
}
@@ -50,55 +83,70 @@ std::string GetKeyUsageString(X509Certificate::OSCertHandle cert_handle) {
std::string GetSerialNumberHexified(
X509Certificate::OSCertHandle cert_handle,
const std::string& alternative_text) {
- // TODO(bulach): implement me.
- return "";
+ ASN1_INTEGER* num = X509_get_serialNumber(cert_handle);
+ const char kSerialNumberSeparator = ':';
+ std::string hex_string = ProcessRawBytesWithSeparators(
+ num->data, num->length, kSerialNumberSeparator, kSerialNumberSeparator);
+ return AlternativeWhenEmpty(hex_string, alternative_text);
}
std::string GetIssuerCommonName(
X509Certificate::OSCertHandle cert_handle,
const std::string& alternative_text) {
- // TODO(bulach): implement me.
- return "";
+ std::string ret;
+ nxou::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
+ NID_commonName, &ret);
+ return AlternativeWhenEmpty(ret, alternative_text);
}
std::string GetIssuerOrgName(
X509Certificate::OSCertHandle cert_handle,
const std::string& alternative_text) {
- // TODO(bulach): implement me.
- return "";
+ std::string ret;
+ nxou::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
+ NID_organizationName, &ret);
+ return AlternativeWhenEmpty(ret, alternative_text);
}
std::string GetIssuerOrgUnitName(
X509Certificate::OSCertHandle cert_handle,
const std::string& alternative_text) {
- // TODO(bulach): implement me.
- return "";
+ std::string ret;
+ nxou::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
+ NID_organizationalUnitName, &ret);
+ return AlternativeWhenEmpty(ret, alternative_text);
}
std::string GetSubjectOrgName(
X509Certificate::OSCertHandle cert_handle,
const std::string& alternative_text) {
- // TODO(bulach): implement me.
- return "";
+ std::string ret;
+ nxou::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
+ NID_organizationName, &ret);
+ return AlternativeWhenEmpty(ret, alternative_text);
}
std::string GetSubjectOrgUnitName(
X509Certificate::OSCertHandle cert_handle,
const std::string& alternative_text) {
- // TODO(bulach): implement me.
- return "";
+ std::string ret;
+ nxou::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
+ NID_organizationalUnitName, &ret);
+ return AlternativeWhenEmpty(ret, alternative_text);
}
std::string GetSubjectCommonName(X509Certificate::OSCertHandle cert_handle,
const std::string& alternative_text) {
- // TODO(bulach): implement me.
- return "";
+ std::string ret;
+ nxou::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
+ NID_commonName, &ret);
+ return AlternativeWhenEmpty(ret, alternative_text);
}
bool GetTimes(X509Certificate::OSCertHandle cert_handle,
base::Time* issued, base::Time* expires) {
- // TODO(bulach): implement me.
- return false;
+ return nxou::ParseDate(X509_get_notBefore(cert_handle), issued) &&
+ nxou::ParseDate(X509_get_notAfter(cert_handle), expires);
}
std::string GetTitle(net::X509Certificate::OSCertHandle cert_handle) {
@@ -107,13 +155,11 @@ std::string GetTitle(net::X509Certificate::OSCertHandle cert_handle) {
}
std::string GetIssuerName(net::X509Certificate::OSCertHandle cert_handle) {
- // TODO(bulach): implement me.
- return "";
+ return GetKeyValuesFromName(X509_get_issuer_name(cert_handle));
}
std::string GetSubjectName(net::X509Certificate::OSCertHandle cert_handle) {
- // TODO(bulach): implement me.
- return "";
+ return GetKeyValuesFromName(X509_get_subject_name(cert_handle));
}
void GetEmailAddresses(net::X509Certificate::OSCertHandle cert_handle,
@@ -138,22 +184,34 @@ void GetExtensions(
}
std::string HashCertSHA256(net::X509Certificate::OSCertHandle cert_handle) {
- // TODO(bulach): implement me.
- return "";
+ unsigned char sha256_data[SHA256_DIGEST_LENGTH] = {0};
+ unsigned int sha256_size = sizeof(sha256_data);
+ int ret = X509_digest(cert_handle, EVP_sha256(), sha256_data, &sha256_size);
+ CHECK(ret);
+ CHECK_EQ(sha256_size, sizeof(sha256_data));
+ return ProcessRawBytes(sha256_data, sha256_size);
}
std::string HashCertSHA1(net::X509Certificate::OSCertHandle cert_handle) {
- // TODO(bulach): implement me.
- return "";
+ unsigned char sha1_data[SHA_DIGEST_LENGTH] = {0};
+ unsigned int sha1_size = sizeof(sha1_data);
+ int ret = X509_digest(cert_handle, EVP_sha1(), sha1_data, &sha1_size);
+ CHECK(ret);
+ CHECK_EQ(sha1_size, sizeof(sha1_data));
+ return ProcessRawBytes(sha1_data, sha1_size);
}
void GetCertChainFromCert(net::X509Certificate::OSCertHandle cert_handle,
net::X509Certificate::OSCertHandles* cert_handles) {
- // TODO(bulach): implement me.
+ // TODO(bulach): how to get the chain out of a certificate?
+ cert_handles->push_back(net::X509Certificate::DupOSCertHandle(cert_handle));
}
void DestroyCertChain(net::X509Certificate::OSCertHandles* cert_handles) {
- // TODO(bulach): implement me.
+ for (net::X509Certificate::OSCertHandles::iterator i = cert_handles->begin();
+ i != cert_handles->end(); ++i)
+ X509_free(*i);
+ cert_handles->clear();
}
std::string GetDerString(net::X509Certificate::OSCertHandle cert_handle) {
diff --git a/chrome/common/notification_registrar.cc b/chrome/common/notification_registrar.cc
index 7ec5cda..d413585 100644
--- a/chrome/common/notification_registrar.cc
+++ b/chrome/common/notification_registrar.cc
@@ -47,10 +47,9 @@ NotificationRegistrar::~NotificationRegistrar() {
void NotificationRegistrar::Add(NotificationObserver* observer,
NotificationType type,
const NotificationSource& source) {
- Record record = { observer, type, source, PlatformThread::CurrentId() };
+ DCHECK(!IsRegistered(observer, type, source)) << "Duplicate registration.";
- DCHECK(std::find(registered_.begin(), registered_.end(), record) ==
- registered_.end()) << "Duplicate registration.";
+ Record record = { observer, type, source, PlatformThread::CurrentId() };
registered_.push_back(record);
NotificationService::current()->AddObserver(observer, type, source);
@@ -59,16 +58,16 @@ void NotificationRegistrar::Add(NotificationObserver* observer,
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()) {
+ if (!IsRegistered(observer, type, source)) {
NOTREACHED() << "Trying to remove unregistered observer of type " <<
type.value << " from list of size " << registered_.size() << ".";
return;
}
- CheckCalledOnValidThread(found->thread_id);
+ Record record = { observer, type, source };
+ RecordVector::iterator found = std::find(
+ registered_.begin(), registered_.end(), record);
+ CheckCalledOnValidThread(found->thread_id);
registered_.erase(found);
// This can be NULL if our owner outlives the NotificationService, e.g. if our
@@ -106,3 +105,11 @@ void NotificationRegistrar::RemoveAll() {
bool NotificationRegistrar::IsEmpty() const {
return registered_.empty();
}
+
+bool NotificationRegistrar::IsRegistered(NotificationObserver* observer,
+ NotificationType type,
+ const NotificationSource& source) {
+ Record record = { observer, type, source };
+ return std::find(registered_.begin(), registered_.end(), record) !=
+ registered_.end();
+}
diff --git a/chrome/common/notification_registrar.h b/chrome/common/notification_registrar.h
index 1207d99..9048560 100644
--- a/chrome/common/notification_registrar.h
+++ b/chrome/common/notification_registrar.h
@@ -42,6 +42,12 @@ class NotificationRegistrar {
// Returns true if no notifications are registered.
bool IsEmpty() const;
+ // Returns true if there is already a registered notification with the
+ // specified details.
+ bool IsRegistered(NotificationObserver* observer,
+ NotificationType type,
+ const NotificationSource& source);
+
private:
struct Record;
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 4fa44f2..ba8280d 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -107,13 +107,24 @@ class NotificationType {
FRAME_PROVISIONAL_LOAD_START,
// The provisional load for a frame was committed. The source is a
- // NavigationController corresponding to the tab in which the load occured.
+ // NavigationController corresponding to the tab in which the load occurred.
// Details is a ProvisionalLoadDetails object. In contrast to
// NAV_ENTRY_COMMITTED, this notification is sent when the load was
// committed, even if no navigation entry was committed (such as
// AUTO_SUBFRAME navigations).
FRAME_PROVISIONAL_LOAD_COMMITTED,
+ // The DOM for a frame was fully constructed, but referenced resources
+ // might not be fully loaded yet. The source is a
+ // Source<NavigationController> corresponding to the tab in which the load
+ // occurred. Details are the long long frame ID.
+ FRAME_DOM_CONTENT_LOADED,
+
+ // The frame finished loading. The source is a Source<NavigationController>
+ // corresponding to the tab in which the load occurred. Details are the
+ // long long frame ID.
+ FRAME_DID_FINISH_LOAD,
+
// 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
@@ -631,6 +642,10 @@ class NotificationType {
// the details is history::URLsDeletedDetails that lists the deleted URLs.
HISTORY_URLS_DELETED,
+ // Sent when a keyword search term is updated. The source is the Profile and
+ // the details are history::KeywordSearchTermDetails
+ HISTORY_KEYWORD_SEARCH_TERM_UPDATED,
+
// 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).
@@ -649,6 +664,12 @@ class NotificationType {
// none and the source is a Profile*.
PROFILE_DESTROYED,
+ // TopSites ----------------------------------------------------------------
+
+ // Sent by TopSites when it finishes loading. The source is the profile the
+ // details the TopSites.
+ TOP_SITES_LOADED,
+
// Thumbnails---------------------------------------------------------------
// Sent by the ThumbnailGenerator whenever a render widget host
@@ -695,6 +716,10 @@ class NotificationType {
// NoDetails.
TEMPLATE_URL_MODEL_LOADED,
+ // Sent when a TemplateURL is removed from the model. The source is the
+ // Profile, and the details the id of the TemplateURL being removed.
+ TEMPLATE_URL_REMOVED,
+
// 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.
@@ -946,14 +971,28 @@ class NotificationType {
// key of the entry that was affected.
AUTOFILL_ENTRIES_CHANGED,
+ // DEPRECATED
+ // TODO(dhollowa): Remove this once Sync has migrated to GUID-based
+ // notifications. http://crbug.com/58813
// Sent when an AutoFillProfile has been added/removed/updated in the
// WebDatabase. The detail is an AutofillProfileChange.
AUTOFILL_PROFILE_CHANGED,
+ // Sent when an AutoFillProfile has been added/removed/updated in the
+ // WebDatabase. The detail is an AutofillProfileChangeGUID.
+ AUTOFILL_PROFILE_CHANGED_GUID,
+
+ // DEPRECATED
+ // TODO(dhollowa): Remove this once Sync has migrated to GUID-based
+ // notifications. http://crbug.com/58813
// Sent when an Autofill CreditCard has been added/removed/updated in the
// WebDatabase. The detail is an AutofillCreditCardChange.
AUTOFILL_CREDIT_CARD_CHANGED,
+ // Sent when an Autofill CreditCard has been added/removed/updated in the
+ // WebDatabase. The detail is an AutofillCreditCardChangeGUID.
+ AUTOFILL_CREDIT_CARD_CHANGED_GUID,
+
// This notification is sent whenever the web database service has finished
// loading the web database. No details are expected.
WEB_DATABASE_LOADED,
@@ -978,6 +1017,17 @@ class NotificationType {
// expected.
UPGRADE_RECOMMENDED,
+ // Software incompatibility notifications ----------------------------------
+
+ // Sent when Chrome has finished compiling the list of loaded modules (and
+ // other modules of interest). No details are expected.
+ MODULE_LIST_ENUMERATED,
+
+ // Sent when Chrome detects an incompatible module. Details is a boolean
+ // specifying true if one or more confirmed bad modules were found or false
+ // if only suspected bad modules were found.
+ MODULE_INCOMPATIBILITY_DETECTED,
+
// Accessibility Notifications ---------------------------------------------
// Notification that a window in the browser UI (not the web content)
@@ -1022,15 +1072,6 @@ class NotificationType {
// TabSpecificContentSettings object, there are no details.
COLLECTED_COOKIES_SHOWN,
- // Sent when the default geolocation setting has changed. The source is the
- // GeolocationContentSettingsMap, the details are None.
- GEOLOCATION_DEFAULT_CHANGED,
-
- // Sent when a non-default setting in the the geolocation content settings
- // map has changed. The source is the GeolocationContentSettingsMap, the
- // details are None.
- GEOLOCATION_SETTINGS_CHANGED,
-
// Sent when the default setting for desktop notifications has changed.
// The source is the DesktopNotificationService, the details are None.
DESKTOP_NOTIFICATION_DEFAULT_CHANGED,
@@ -1123,13 +1164,12 @@ class NotificationType {
TOKEN_UPDATED,
// Sent when a user signs into Google services such as sync.
- // The source is the SigninManager instance. The details are a
- // GoogleServiceSignin object.
+ // The source is the Profile. The details are a GoogleServiceSignin object.
GOOGLE_SIGNIN_SUCCESSFUL,
// Sent when a user fails to sign into Google services such as sync.
- // The source is the SigninManager instance. The details are a
- // GoogleServiceAuthError object.
+ // The source is the Profile. The details are a GoogleServiceAuthError
+ // object.
GOOGLE_SIGNIN_FAILED,
// AutoFill Notifications --------------------------------------------------
@@ -1212,6 +1252,9 @@ class NotificationType {
// Sent each time the InstantController is updated.
INSTANT_CONTROLLER_UPDATED,
+ // Sent each time the InstantController shows the InstantLoader.
+ INSTANT_CONTROLLER_SHOWN,
+
// 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
@@ -1225,6 +1268,10 @@ class NotificationType {
// The detail of this notification is not used.
POLICY_CHANGED,
+ // This notification is sent whenever the device token becomes available
+ // that the policy subsystem uses to fetch policy from the cloud.
+ DEVICE_TOKEN_AVAILABLE,
+
// Count (must be last) ----------------------------------------------------
// Used to determine the number of notification types. Not valid as
// a type parameter when registering for or posting notifications.
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
index a83b41a..6cee704 100644
--- a/chrome/common/plugin_messages_internal.h
+++ b/chrome/common/plugin_messages_internal.h
@@ -438,7 +438,7 @@ IPC_BEGIN_MESSAGES(PluginHost)
gfx::PluginWindowHandle /* window */,
int32 /* width */,
int32 /* height */,
- uint64 /* identifier for IOSurface */)
+ uint64 /* surface_id */)
// On the Mac, shared memory can't be allocated in the sandbox, so
@@ -458,8 +458,9 @@ IPC_BEGIN_MESSAGES(PluginHost)
// 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 */)
+ IPC_MESSAGE_ROUTED2(PluginHostMsg_AcceleratedSurfaceBuffersSwapped,
+ gfx::PluginWindowHandle /* window */,
+ uint64 /* surface_id */)
#endif
IPC_END_MESSAGES(PluginHost)
diff --git a/chrome/common/policy_constants.cc b/chrome/common/policy_constants.cc
index ffe93b4..f56f2b2 100644
--- a/chrome/common/policy_constants.cc
+++ b/chrome/common/policy_constants.cc
@@ -50,10 +50,13 @@ const char kApplicationLocaleValue[] = "ApplicationLocaleValue";
const char kSyncDisabled[] = "SyncDisabled";
const char kExtensionInstallAllowList[] = "ExtensionInstallWhitelist";
const char kExtensionInstallDenyList[] = "ExtensionInstallBlacklist";
+const char kExtensionInstallForceList[] = "ExtensionInstallForcelist";
const char kShowHomeButton[] = "ShowHomeButton";
const char kPrintingEnabled[] = "PrintingEnabled";
const char kJavascriptEnabled[] = "JavascriptEnabled";
const char kSavingBrowserHistoryDisabled[] = "SavingBrowserHistoryDisabled";
+const char kDeveloperToolsDisabled[] = "DeveloperToolsDisabled";
+const char kBlockThirdPartyCookies[] = "BlockThirdPartyCookies";
// Chrome Frame specific policy constants
const char kChromeFrameRendererSettings[] = "ChromeFrameRendererSettings";
diff --git a/chrome/common/policy_constants.h b/chrome/common/policy_constants.h
index cebf36b..1bff710 100644
--- a/chrome/common/policy_constants.h
+++ b/chrome/common/policy_constants.h
@@ -47,10 +47,13 @@ extern const char kApplicationLocaleValue[];
extern const char kSyncDisabled[];
extern const char kExtensionInstallAllowList[];
extern const char kExtensionInstallDenyList[];
+extern const char kExtensionInstallForceList[];
extern const char kShowHomeButton[];
extern const char kPrintingEnabled[];
extern const char kJavascriptEnabled[];
extern const char kSavingBrowserHistoryDisabled[];
+extern const char kDeveloperToolsDisabled[];
+extern const char kBlockThirdPartyCookies[];
// Chrome Frame specific policy constants
extern const char kChromeFrameRendererSettings[];
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 27bc3b7..9c91912 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -212,9 +212,9 @@ const char kInstantConfirmDialogShown[] = "instant.confirm_dialog_shown";
// Boolean pref indicating if instant is enabled.
const char kInstantEnabled[] = "instant.enabled";
-#if defined(USE_NSS)
+#if defined(USE_NSS) || defined(USE_OPENSSL)
// Prefs for SSLConfigServicePref. Currently, these are only present on
-// and used by NSS-using OSes.
+// and used by NSS/OpenSSL using OSes.
const char kCertRevocationCheckingEnabled[] = "ssl.rev_checking.enabled";
const char kSSL2Enabled[] = "ssl.ssl2.enabled";
const char kSSL3Enabled[] = "ssl.ssl3.enabled";
@@ -397,10 +397,6 @@ const char kLabsAdvancedFilesystemEnabled[] =
// A boolean pref which turns on the mediaplayer.
const char kLabsMediaplayerEnabled[] = "settings.labs.mediaplayer";
-// An integer pref which maps to the extension state for Talk.
-const char kLabsTalkEnabled[] =
- "extensions.settings.ggnioahjipcehijkhpdjekioddnjoben.state";
-
// A boolean pref that turns on screen locker.
const char kEnableScreenLock[] = "settings.enable_screen_lock";
@@ -484,7 +480,7 @@ const char kPluginsPluginsBlacklist[] = "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 char kPluginsEnabledInternalPDF[] = "plugins.enabled_internal_pdf2";
+const char kPluginsEnabledInternalPDF[] = "plugins.enabled_internal_pdf3";
// Boolean that indicates whether we should check if we are the default browser
// on start-up.
@@ -541,6 +537,9 @@ const char kBlockNonsandboxedPlugins[] = "profile.block_nonsandboxed_plugins";
// storage, etc..) should be deleted on exit.
const char kClearSiteDataOnExit[] = "profile.clear_site_data_on_exit";
+// Double that indicates the default zoom level.
+const char kDefaultZoomLevel[] = "profile.default_zoom_level";
+
// Dictionary that maps hostnames to zoom levels. Hosts not in this pref will
// be displayed at the default zoom level.
const char kPerHostZoomLevels[] = "profile.per_host_zoom_levels";
@@ -731,10 +730,6 @@ const char kBrowserWindowPlacement[] = "browser.window_placement";
// manager window to restore on startup.
const char kTaskManagerWindowPlacement[] = "task_manager.window_placement";
-// A collection of position, size, and other data relating to the page info
-// window to restore on startup.
-const char kPageInfoWindowPlacement[] = "page_info.window_placement";
-
// A collection of position, size, and other data relating to the keyword
// editor window to restore on startup.
const char kKeywordEditorWindowPlacement[] = "keyword_editor.window_placement";
@@ -768,7 +763,7 @@ const char kSaveFileDefaultDirectory[] = "savefile.default_directory";
// String which specifies the last directory that was chosen for uploading
// or opening a file.
-extern const char kSelectFileLastDirectory[] = "selectfile.last_directory";
+const char kSelectFileLastDirectory[] = "selectfile.last_directory";
// Extensions which should be opened upon completion.
const char kDownloadExtensionsToOpen[] = "download.extensions_to_open";
@@ -897,6 +892,13 @@ const char kExtensionInstallAllowList[] = "extensions.install.allowlist";
// Google controlled.
const char kExtensionInstallDenyList[] = "extensions.install.denylist";
+// A list containing extensions that Chrome will silently install
+// at startup time. It is a list of strings, each string contains
+// an extension ID and an update URL, delimited by a semicolon.
+// This preference is set by an admin policy, and meant to be only
+// accessed through ExternalPolicyExtensionProvider.
+const char kExtensionInstallForceList[] = "extensions.install.forcelist";
+
// Time of the last, and next scheduled, extensions auto-update checks.
const char kLastExtensionsUpdateCheck[] = "extensions.autoupdate.last_check";
const char kNextExtensionsUpdateCheck[] = "extensions.autoupdate.next_check";
@@ -942,6 +944,8 @@ const char kNTPPrefVersion[] = "ntp.pref_version";
const char kNTPCustomLogoStart[] = "ntp.alt_logo_start";
const char kNTPCustomLogoEnd[] = "ntp.alt_logo_end";
+const char kDevToolsDisabled[] = "devtools.disabled";
+
// A boolean specifying whether dev tools window should be opened docked.
const char kDevToolsOpenDocked[] = "devtools.open_docked";
@@ -1011,12 +1015,22 @@ const char kLoginDatabaseMigrated[] = "login_database.migrated";
// The root URL of the cloud print service.
const char kCloudPrintServiceURL[] = "cloud_print.service_url";
+// The last requested size of the dialog as it was closed.
+const char kCloudPrintDialogWidth[] = "cloud_print.dialog_size.width";
+const char kCloudPrintDialogHeight[] = "cloud_print.dialog_size.height";
+
const char kRemotingHasSetupCompleted[] = "remoting.has_setup_completed";
// The list of BackgroundContents that should be loaded when the browser
// launches.
const char kRegisteredBackgroundContents[] = "background_contents.registered";
+#if defined(OS_CHROMEOS)
+// Dictionary for transient storage of settings that should go into signed
+// settings storage before owner has been assigned.
+const char kSignedSettingsTempStorage[] = "signed_settings_temp_storage";
+#endif
+
// *************** SERVICE PREFS ***************
// These are attached to the service process.
@@ -1030,9 +1044,9 @@ const char kCloudPrintAuthToken[] = "cloud_print.auth_token";
const char kCloudPrintXMPPAuthToken[] = "cloud_print.xmpp_auth_token";
// The email address of the account used to authenticate with the Cloud Print
// server.
-extern const char kCloudPrintEmail[] = "cloud_print.email";
+const char kCloudPrintEmail[] = "cloud_print.email";
// Settings specific to underlying print system.
-extern const char kCloudPrintPrintSystemSettings[] =
+const char kCloudPrintPrintSystemSettings[] =
"cloud_print.print_system_settings";
// Used by the service process to determine if the remoting host is enabled.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 7f7acdc..0d5275c 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -75,7 +75,7 @@ extern const char kDisableSpdy[];
extern const char kCookiePromptExpanded[];
extern const char kInstantConfirmDialogShown[];
extern const char kInstantEnabled[];
-#if defined(USE_NSS)
+#if defined(USE_NSS) || defined(USE_OPENSSL)
extern const char kCertRevocationCheckingEnabled[];
extern const char kSSL2Enabled[];
extern const char kSSL3Enabled[];
@@ -146,7 +146,6 @@ extern const char kLanguageXkbAutoRepeatInterval[];
extern const char kAccessibilityEnabled[];
extern const char kLabsAdvancedFilesystemEnabled[];
extern const char kLabsMediaplayerEnabled[];
-extern const char kLabsTalkEnabled[];
extern const char kEnableScreenLock[];
#endif
extern const char kIpcDisabledMessages[];
@@ -202,6 +201,7 @@ extern const char kContentSettingsPatterns[];
extern const char kBlockThirdPartyCookies[];
extern const char kBlockNonsandboxedPlugins[];
extern const char kClearSiteDataOnExit[];
+extern const char kDefaultZoomLevel[];
extern const char kPerHostZoomLevels[];
extern const char kAutoFillEnabled[];
extern const char kAutoFillAuxiliaryProfilesEnabled[];
@@ -261,7 +261,6 @@ extern const char kUninstallLastObservedRunTimeSec[];
extern const char kBrowserWindowPlacement[];
extern const char kTaskManagerWindowPlacement[];
-extern const char kPageInfoWindowPlacement[];
extern const char kKeywordEditorWindowPlacement[];
extern const char kPreferencesWindowPlacement[];
extern const char kMemoryCacheSize[];
@@ -326,6 +325,8 @@ extern const char kNextExtensionsUpdateCheck[];
extern const char kExtensionInstallAllowList[];
extern const char kExtensionInstallDenyList[];
+extern const char kExtensionInstallForceList[];
+
extern const char kExtensionBlacklistUpdateVersion[];
extern const char kExtensionSidebarWidth[];
@@ -341,6 +342,7 @@ extern const char kNTPPrefVersion[];
extern const char kNTPCustomLogoStart[];
extern const char kNTPCustomLogoEnd[];
+extern const char kDevToolsDisabled[];
extern const char kDevToolsOpenDocked[];
extern const char kDevToolsSplitLocation[];
extern const char kSyncSessions[];
@@ -373,8 +375,10 @@ extern const char kGeolocationContentSettings[];
extern const char kLoginDatabaseMigrated[];
-extern const char kCloudPrintProxyEnabled[];
extern const char kCloudPrintServiceURL[];
+extern const char kCloudPrintDialogWidth[];
+extern const char kCloudPrintDialogHeight[];
+extern const char kCloudPrintProxyEnabled[];
extern const char kCloudPrintProxyId[];
extern const char kCloudPrintAuthToken[];
extern const char kCloudPrintXMPPAuthToken[];
@@ -390,6 +394,10 @@ extern const char kProxyServer[];
extern const char kProxyPacUrl[];
extern const char kProxyBypassList[];
+#if defined(OS_CHROMEOS)
+extern const char kSignedSettingsTempStorage[];
+#endif
+
extern const char kRegisteredBackgroundContents[];
} // namespace prefs
diff --git a/chrome/common/pref_store.h b/chrome/common/pref_store.h
index 192ce14..7011eba 100644
--- a/chrome/common/pref_store.h
+++ b/chrome/common/pref_store.h
@@ -55,7 +55,7 @@ class PrefStore {
// DictionaryValue. Instead, it should have getters that return a
// richer set of information for a pref, including if the store
// wants to return the default value for a preference.
- virtual DictionaryValue* prefs() = 0;
+ virtual DictionaryValue* prefs() const = 0;
virtual PrefReadError ReadPrefs() = 0;
diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc
index f437bf4..2a42c6c 100644
--- a/chrome/common/render_messages.cc
+++ b/chrome/common/render_messages.cc
@@ -14,6 +14,7 @@
#include "chrome/common/render_messages_params.h"
#include "chrome/common/resource_response.h"
#include "chrome/common/serialized_script_value.h"
+#include "chrome/common/speech_input_result.h"
#include "chrome/common/thumbnail_score.h"
#include "gfx/rect.h"
#include "ipc/ipc_channel_handle.h"
@@ -863,7 +864,7 @@ bool ParamTraits<URLPattern>::Read(const Message* m, void** iter,
return false;
p->set_valid_schemes(valid_schemes);
- return p->Parse(spec);
+ return URLPattern::PARSE_SUCCESS == p->Parse(spec);
}
void ParamTraits<URLPattern>::Log(const param_type& p, std::string* l) {
@@ -1229,4 +1230,26 @@ void ParamTraits<PepperDirEntry>::Log(const param_type& p, std::string* l) {
l->append(")");
}
+void ParamTraits<speech_input::SpeechInputResultItem>::Write(
+ Message* m, const param_type& p) {
+ WriteParam(m, p.utterance);
+ WriteParam(m, p.confidence);
+}
+
+bool ParamTraits<speech_input::SpeechInputResultItem>::Read(const Message* m,
+ void** iter,
+ param_type* p) {
+ return ReadParam(m, iter, &p->utterance) &&
+ ReadParam(m, iter, &p->confidence);
+}
+
+void ParamTraits<speech_input::SpeechInputResultItem>::Log(const param_type& p,
+ std::string* l) {
+ l->append("(");
+ LogParam(p.utterance, l);
+ l->append(":");
+ LogParam(p.confidence, l);
+ l->append(")");
+}
+
} // namespace IPC
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index da54616..fb68afa 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -23,7 +23,6 @@
#include "chrome/common/translate_errors.h"
#include "chrome/common/view_types.h"
#include "chrome/common/webkit_param_traits.h"
-#include "gfx/native_widget_types.h"
#include "ipc/ipc_message_utils.h"
#include "ipc/ipc_platform_file.h" // ifdefed typedef.
#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
@@ -53,6 +52,10 @@ namespace webkit_blob {
class BlobData;
}
+namespace speech_input {
+struct SpeechInputResultItem;
+}
+
namespace webkit_glue {
struct FormData;
class FormField;
@@ -312,7 +315,7 @@ struct ParamTraits<gfx::NativeView> {
}
static void Log(const param_type& p, std::string* l) {
- l->append(StringPrintf("<gfx::NativeView>"));
+ l->append(base::StringPrintf("<gfx::NativeView>"));
}
};
@@ -627,6 +630,14 @@ struct ParamTraits<PepperDirEntry> {
static void Log(const param_type& p, std::string* l);
};
+template <>
+struct ParamTraits<speech_input::SpeechInputResultItem> {
+ typedef speech_input::SpeechInputResultItem 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::string* l);
+};
+
} // namespace IPC
#define MESSAGES_INTERNAL_FILE "chrome/common/render_messages_internal.h"
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index b8e9a70..f00c806 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -13,6 +13,7 @@
#include "build/build_config.h"
#include "base/file_path.h"
+#include "base/file_util_proxy.h"
#include "base/nullable_string16.h"
#include "base/platform_file.h"
#include "base/sync_socket.h"
@@ -21,6 +22,7 @@
#include "chrome/common/nacl_types.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/page_zoom.h"
+#include "chrome/common/speech_input_result.h"
#include "chrome/common/translate_errors.h"
#include "chrome/common/window_container_type.h"
#include "ipc/ipc_message_macros.h"
@@ -49,12 +51,6 @@ class SkBitmap;
struct ThumbnailScore;
class WebCursor;
-namespace base {
-namespace file_util_proxy {
-struct Entry;
-}
-}
-
namespace gfx {
class Rect;
}
@@ -165,6 +161,24 @@ IPC_BEGIN_MESSAGES(View)
int /* document_cookie */,
bool /* success */)
+ // Tells the render view to switch the CSS to print media type, renders every
+ // requested pages for print preview.
+ IPC_MESSAGE_ROUTED0(ViewMsg_PrintPreview)
+
+#if defined(OS_MACOSX) || defined(OS_WIN)
+ // Sends back to the browser the rendered "printed page" for preview 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_PageReadyForPreview,
+ ViewHostMsg_DidPrintPage_Params /* page content */)
+#else
+ // Sends back to the browser the rendered "printed page" for preview 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_PagesReadyForPreview,
+ int /* fd in browser */)
+#endif
+
// 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
@@ -189,12 +203,6 @@ IPC_BEGIN_MESSAGES(View)
// 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
@@ -229,6 +237,11 @@ IPC_BEGIN_MESSAGES(View)
// node.
IPC_MESSAGE_ROUTED1(ViewMsg_SetInitialFocus, bool /* reverse */)
+ // Tells the renderer to scroll the currently focused node into view only if
+ // the currently focused node is a Text node (textfield, text area or content
+ // editable divs).
+ IPC_MESSAGE_ROUTED0(ViewMsg_ScrollFocusedEditableNodeIntoView)
+
// Tells the renderer to perform the specified navigation, interrupting any
// existing navigation.
IPC_MESSAGE_ROUTED1(ViewMsg_Navigate, ViewMsg_Navigate_Params)
@@ -407,6 +420,12 @@ IPC_BEGIN_MESSAGES(View)
IPC_MESSAGE_ROUTED1(ViewMsg_Zoom,
PageZoom::Function /* function */)
+ // Set 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_SetZoomLevel,
+ double /* zoom_level */)
+
// 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.
@@ -803,6 +822,20 @@ IPC_BEGIN_MESSAGES(View)
// Used to instruct the RenderView to send back updates to the preferred size.
IPC_MESSAGE_ROUTED1(ViewMsg_EnablePreferredSizeChangedMode, int /*flags*/)
+ IPC_MESSAGE_ROUTED4(ViewMsg_SearchBoxChange,
+ string16 /*value*/,
+ bool /*verbatim*/,
+ int /*selection_start*/,
+ int /*selection_end*/)
+ IPC_MESSAGE_ROUTED2(ViewMsg_SearchBoxSubmit,
+ string16 /*value*/,
+ bool /*verbatim*/)
+ IPC_MESSAGE_ROUTED0(ViewMsg_SearchBoxCancel)
+ IPC_MESSAGE_ROUTED1(ViewMsg_SearchBoxResize,
+ gfx::Rect /*search_box_bounds*/)
+ IPC_MESSAGE_ROUTED1(ViewMsg_DetermineIfPageSupportsInstant,
+ string16 /*value*/)
+
// Used to tell the renderer not to add scrollbars with height and
// width below a threshold.
IPC_MESSAGE_ROUTED1(ViewMsg_DisableScrollbarsForSmallWindows,
@@ -1033,7 +1066,7 @@ IPC_BEGIN_MESSAGES(View)
// Relay a speech recognition result, either partial or final.
IPC_MESSAGE_ROUTED2(ViewMsg_SpeechInput_SetRecognitionResult,
int /* request id */,
- string16 /* result */)
+ speech_input::SpeechInputResultArray /* result */)
// Indicate that speech recognizer has stopped recording and started
// recognition.
@@ -1065,7 +1098,7 @@ IPC_BEGIN_MESSAGES(View)
base::PlatformFileInfo)
IPC_MESSAGE_CONTROL3(ViewMsg_FileSystem_DidReadDirectory,
int /* request_id */,
- std::vector<base::file_util_proxy::Entry> /* entries */,
+ std::vector<base::FileUtilProxy::Entry> /* entries */,
bool /* has_more */)
IPC_MESSAGE_CONTROL3(ViewMsg_FileSystem_DidWrite,
@@ -1088,6 +1121,10 @@ IPC_BEGIN_MESSAGES(View)
IPC_MESSAGE_CONTROL1(ViewMsg_SetPhishingModel,
IPC::PlatformFileForTransit /* model_file */)
+ // External popup menus.
+ IPC_MESSAGE_ROUTED1(ViewMsg_SelectPopupMenuItem,
+ int /* selected index, -1 means no selection */)
+
IPC_END_MESSAGES(View)
@@ -1185,7 +1222,12 @@ IPC_BEGIN_MESSAGES(ViewHost)
std::string /* state */)
// Notifies the browser that a document has been loaded in a frame.
- IPC_MESSAGE_ROUTED0(ViewHostMsg_DocumentLoadedInFrame)
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DocumentLoadedInFrame,
+ long long /* frame_id */)
+
+ // Notifies the browser that a frame finished loading.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DidFinishLoad,
+ long long /* frame_id */)
// Changes the title for the page in the UI when the page is navigated or the
// title changes.
@@ -1268,14 +1310,6 @@ IPC_BEGIN_MESSAGES(ViewHost)
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,
@@ -1289,7 +1323,12 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED0(ViewHostMsg_Focus)
IPC_MESSAGE_ROUTED0(ViewHostMsg_Blur)
- IPC_MESSAGE_ROUTED0(ViewHostMsg_FocusedNodeChanged)
+
+ // Message sent from renderer to the browser when focus changes inside the
+ // webpage. The parameter says whether the newly focused element needs
+ // keyboard input (true for textfields, text areas and content editable divs).
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_FocusedNodeChanged,
+ bool /* is_editable_node */)
// Returns the window location of the given window.
// TODO(shess): Provide a mapping from reply_msg->routing_id() to
@@ -1782,8 +1821,8 @@ IPC_BEGIN_MESSAGES(ViewHost)
std::string /* value */)
// Send back a string to be recorded by UserMetrics.
- IPC_MESSAGE_ROUTED1(ViewHostMsg_UserMetricsRecordAction,
- std::string /* action */)
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_UserMetricsRecordAction,
+ std::string /* action */)
// Send back histograms as vector of pickled-histogram strings.
IPC_MESSAGE_CONTROL2(ViewHostMsg_RendererHistograms,
@@ -1903,6 +1942,9 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED1(ViewHostMsg_DataReceived_ACK,
int /* request_id */)
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_RevealFolderInOS,
+ FilePath /* path */)
+
// Sent when the renderer has processed a DataDownloaded message.
IPC_MESSAGE_ROUTED1(ViewHostMsg_DataDownloaded_ACK,
int /* request_id */)
@@ -2199,14 +2241,15 @@ IPC_BEGIN_MESSAGES(ViewHost)
gfx::PluginWindowHandle /* window */,
int32 /* width */,
int32 /* height */,
- uint64 /* identifier for IOSurface */)
+ uint64 /* surface_id */)
// 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 */)
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_AcceleratedSurfaceBuffersSwapped,
+ gfx::PluginWindowHandle /* window */,
+ uint64 /* surface_id */)
#endif
// A renderer sends this to the browser process when it wants to create a
@@ -2833,10 +2876,12 @@ IPC_BEGIN_MESSAGES(ViewHost)
// Requests the speech input service to start speech recognition on behalf of
// the given |render_view_id|.
- IPC_MESSAGE_CONTROL3(ViewHostMsg_SpeechInput_StartRecognition,
+ IPC_MESSAGE_CONTROL5(ViewHostMsg_SpeechInput_StartRecognition,
int /* render_view_id */,
- int /* request id */,
- gfx::Rect /* element rect in render view coordinates */)
+ int /* request_id */,
+ gfx::Rect /* element_rect */,
+ std::string /* language */,
+ std::string /* grammar */)
// Requests the speech input service to cancel speech recognition on behalf of
// the given |render_view_id|. If speech recognition is not happening nor or
@@ -2869,11 +2914,12 @@ IPC_BEGIN_MESSAGES(ViewHost)
// These are messages sent from the renderer to the browser process.
// WebFrameClient::openFileSystem() message.
- IPC_MESSAGE_CONTROL4(ViewHostMsg_OpenFileSystemRequest,
+ IPC_MESSAGE_CONTROL5(ViewHostMsg_OpenFileSystemRequest,
int /* request_id */,
GURL /* origin_url */,
fileapi::FileSystemType /* type */,
- int64 /* requested_size */)
+ int64 /* requested_size */,
+ bool /* create */)
// WebFileSystem::move() message.
IPC_MESSAGE_CONTROL3(ViewHostMsg_FileSystem_Move,
@@ -2961,9 +3007,13 @@ IPC_BEGIN_MESSAGES(ViewHost)
// Suggest results -----------------------------------------------------------
- IPC_MESSAGE_ROUTED2(ViewHostMsg_SetSuggestResult,
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_SetSuggestions,
int32 /* page_id */,
- std::string /* suggest */)
+ std::vector<std::string> /* suggestions */)
+
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_InstantSupportDetermined,
+ int32 /* page_id */,
+ bool /* result */)
// Client-Side Phishing Detector ---------------------------------------------
// Inform the browser that the current URL is phishing according to the
diff --git a/chrome/common/render_messages_params.cc b/chrome/common/render_messages_params.cc
index 59802b4..a57b076 100644
--- a/chrome/common/render_messages_params.cc
+++ b/chrome/common/render_messages_params.cc
@@ -522,7 +522,7 @@ struct ParamTraits<Extension::Location> {
int val = 0;
if (!ReadParam(m, iter, &val) ||
val < Extension::INVALID ||
- val > Extension::EXTERNAL_PREF_DOWNLOAD)
+ val >= Extension::NUM_LOCATIONS)
return false;
*p = static_cast<param_type>(val);
return true;
@@ -1873,14 +1873,14 @@ void ParamTraits<ViewHostMsg_DomMessage_Params>::Log(const param_type& p,
l->append(")");
}
-void ParamTraits<base::file_util_proxy::Entry>::Write(
+void ParamTraits<base::FileUtilProxy::Entry>::Write(
Message* m,
const param_type& p) {
WriteParam(m, p.name);
WriteParam(m, p.is_directory);
}
-bool ParamTraits<base::file_util_proxy::Entry>::Read(
+bool ParamTraits<base::FileUtilProxy::Entry>::Read(
const Message* m,
void** iter,
param_type* p) {
@@ -1889,7 +1889,7 @@ bool ParamTraits<base::file_util_proxy::Entry>::Read(
ReadParam(m, iter, &p->is_directory);
}
-void ParamTraits<base::file_util_proxy::Entry>::Log(
+void ParamTraits<base::FileUtilProxy::Entry>::Log(
const param_type& p,
std::string* l) {
l->append("(");
diff --git a/chrome/common/render_messages_params.h b/chrome/common/render_messages_params.h
index 2eeff70..d92def3 100644
--- a/chrome/common/render_messages_params.h
+++ b/chrome/common/render_messages_params.h
@@ -1315,8 +1315,8 @@ struct ParamTraits<ViewHostMsg_DomMessage_Params> {
};
template <>
-struct ParamTraits<base::file_util_proxy::Entry> {
- typedef base::file_util_proxy::Entry param_type;
+struct ParamTraits<base::FileUtilProxy::Entry> {
+ typedef base::FileUtilProxy::Entry 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::string* l);
diff --git a/chrome/common/resource_dispatcher_unittest.cc b/chrome/common/resource_dispatcher_unittest.cc
index 8e31ee9..f5828ff 100644
--- a/chrome/common/resource_dispatcher_unittest.cc
+++ b/chrome/common/resource_dispatcher_unittest.cc
@@ -69,10 +69,6 @@ class TestRequestCallback : public ResourceLoaderBridge::Peer {
complete_ = true;
}
- virtual GURL GetURLForDebugging() const {
- return GURL();
- }
-
const std::string& data() const {
return data_;
}
@@ -121,9 +117,7 @@ class ResourceDispatcherTest : public testing::Test,
// received data message with the test contents
base::SharedMemory shared_mem;
- EXPECT_TRUE(shared_mem.Create(std::string(), false, false,
- test_page_contents_len));
- EXPECT_TRUE(shared_mem.Map(test_page_contents_len));
+ EXPECT_TRUE(shared_mem.CreateAndMapAnonymous(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;
@@ -293,14 +287,10 @@ class DeferredResourceLoadingTest : public ResourceDispatcherTest,
const base::Time& completion_time) {
}
- virtual GURL GetURLForDebugging() const {
- return GURL();
- }
-
protected:
virtual void SetUp() {
- EXPECT_EQ(true, shared_handle_.Create("DeferredResourceLoaderTest", false,
- false, 100));
+ EXPECT_EQ(true, shared_handle_.CreateNamed("DeferredResourceLoaderTest",
+ false, 100));
ResourceDispatcherTest::SetUp();
}
diff --git a/chrome/common/sandbox_init_wrapper_mac.cc b/chrome/common/sandbox_init_wrapper_mac.cc
index ca21255..d65ee70 100644
--- a/chrome/common/sandbox_init_wrapper_mac.cc
+++ b/chrome/common/sandbox_init_wrapper_mac.cc
@@ -12,10 +12,12 @@
bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
const std::string& process_type) {
+ using sandbox::Sandbox;
+
if (command_line.HasSwitch(switches::kNoSandbox))
return true;
- sandbox::SandboxProcessType sandbox_process_type;
+ Sandbox::SandboxProcessType sandbox_process_type;
FilePath allowed_dir; // Empty by default.
if (process_type.empty()) {
@@ -29,7 +31,7 @@ bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
// this once this flag is removed.
return true;
} else {
- sandbox_process_type = sandbox::SANDBOX_TYPE_RENDERER;
+ sandbox_process_type = Sandbox::SANDBOX_TYPE_RENDERER;
}
} else if (process_type == switches::kExtensionProcess) {
// Extension processes are just renderers [they use RenderMain()] with a
@@ -42,15 +44,15 @@ bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
return true;
} else if (process_type == switches::kUtilityProcess) {
// Utility process sandbox.
- sandbox_process_type = sandbox::SANDBOX_TYPE_UTILITY;
+ sandbox_process_type = Sandbox::SANDBOX_TYPE_UTILITY;
allowed_dir =
command_line.GetSwitchValuePath(switches::kUtilityProcessAllowedDir);
} else if (process_type == switches::kWorkerProcess) {
// Worker process sandbox.
- sandbox_process_type = sandbox::SANDBOX_TYPE_WORKER;
+ 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;
+ sandbox_process_type = Sandbox::SANDBOX_TYPE_NACL_LOADER;
} else if ((process_type == switches::kPluginProcess) ||
(process_type == switches::kProfileImportProcess) ||
(process_type == switches::kGpuProcess) ||
@@ -64,8 +66,8 @@ bool SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line,
}
// Warm up APIs before turning on the sandbox.
- sandbox::SandboxWarmup();
+ Sandbox::SandboxWarmup();
// Actually sandbox the process.
- return sandbox::EnableSandbox(sandbox_process_type, allowed_dir);
+ return Sandbox::EnableSandbox(sandbox_process_type, allowed_dir);
}
diff --git a/chrome/common/sandbox_mac.h b/chrome/common/sandbox_mac.h
index 61a02fc..f16fdb5 100644
--- a/chrome/common/sandbox_mac.h
+++ b/chrome/common/sandbox_mac.h
@@ -6,52 +6,171 @@
#define CHROME_COMMON_SANDBOX_MAC_H_
#pragma once
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/hash_tables.h"
+#include "base/gtest_prod_util.h"
+
class FilePath;
+#if __OBJC__
+@class NSArray;
+@class NSString;
+#else
+class NSArray;
+class NSString;
+#endif
+
namespace sandbox {
-enum SandboxProcessType {
- SANDBOX_TYPE_FIRST_TYPE, // Placeholder to ease iteration.
+// Class representing a substring of the sandbox profile tagged with its type.
+class SandboxSubstring {
+ public:
+ enum SandboxSubstringType {
+ PLAIN, // Just a plain string, no escaping necessary.
+ LITERAL, // Escape for use in (literal ...) expression.
+ REGEX, // Escape for use in (regex ...) expression.
+ };
- SANDBOX_TYPE_RENDERER = SANDBOX_TYPE_FIRST_TYPE,
+ SandboxSubstring() {}
- // 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,
+ explicit SandboxSubstring(const std::string& value)
+ : value_(value),
+ type_(PLAIN) {}
- // Utility process is as restrictive as the worker process except full access
- // is allowed to one configurable directory.
- SANDBOX_TYPE_UTILITY,
+ SandboxSubstring(const std::string& value, SandboxSubstringType type)
+ : value_(value),
+ type_(type) {}
- // Native Client sandbox for the user's untrusted code.
- SANDBOX_TYPE_NACL_LOADER,
+ const std::string& value() { return value_; }
+ SandboxSubstringType type() { return type_; }
- SANDBOX_AFTER_TYPE_LAST_TYPE, // Placeholder to ease iteration.
+ private:
+ std::string value_;
+ SandboxSubstringType type_;
};
-// 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);
+class Sandbox {
+ public:
+ // A map of variable name -> string to substitute in its place.
+ typedef base::hash_map<std::string, SandboxSubstring>
+ SandboxVariableSubstitions;
+
+ enum SandboxProcessType {
+ SANDBOX_TYPE_FIRST_TYPE, // Placeholder to ease iteration.
+
+ SANDBOX_TYPE_RENDERER = SANDBOX_TYPE_FIRST_TYPE,
+
+ // The worker process 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 sandbox for the user's untrusted code.
+ 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.
+ static 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 .
+ //
+ // Returns true on success, false if an error occurred enabling the sandbox.
+ static bool EnableSandbox(SandboxProcessType sandbox_type,
+ const FilePath& allowed_dir);
+
+
+ // Exposed for testing purposes, used by an accessory function of our tests
+ // so we can't use FRIEND_TEST.
+
+ // Build the Sandbox command necessary to allow access to a named directory
+ // indicated by |allowed_dir|.
+ // Returns a string containing the sandbox profile commands necessary to allow
+ // access to that directory or nil if an error occured.
+
+ // The header comment for PostProcessSandboxProfile() explains how variable
+ // substition works in sandbox templates.
+ // The returned string contains embedded variables. The function fills in
+ // |substitutions| to contain the values for these variables.
+ static NSString* BuildAllowDirectoryAccessSandboxString(
+ const FilePath& allowed_dir,
+ SandboxVariableSubstitions* substitutions);
+
+ // Assemble the final sandbox profile from a template by removing comments
+ // and substituting variables.
+ //
+ // |sandbox_template| is a string which contains 2 entitites to operate on:
+ //
+ // - Comments - The sandbox comment syntax is used to make the OS sandbox
+ // optionally ignore commands it doesn't support. e.g.
+ // ;10.6_ONLY (foo)
+ // Where (foo) is some command that is only supported on OS X 10.6.
+ // The ;10.6_ONLY comment can then be removed from the template to enable
+ // (foo) as appropriate.
+ //
+ // - Variables - denoted by @variable_name@ . These are defined in the
+ // sandbox template in cases where another string needs to be substituted at
+ // runtime. e.g. @HOMEDIR_AS_LITERAL@ is substituted at runtime for the user's
+ // home directory escaped appropriately for a (literal ...) expression.
+ //
+ // |comments_to_remove| is a list of NSStrings containing the comments to
+ // remove.
+ // |substitutions| is a hash of "variable name" -> "string to substitute".
+ // Where the replacement string is tagged with information on how it is to be
+ // escaped e.g. used as part of a regex string or a literal.
+ //
+ // On output |final_sandbox_profile_str| contains the final sandbox profile.
+ // Returns true on success, false otherwise.
+ static bool PostProcessSandboxProfile(
+ NSString* in_sandbox_data,
+ NSArray* comments_to_remove,
+ SandboxVariableSubstitions& substitutions,
+ std::string *final_sandbox_profile_str);
+
+ private:
+ // Escape |src_utf8| for use in a plain string variable in a sandbox
+ // configuraton file. On return |dst| is set to the quoted output.
+ // Returns: true on success, false otherwise.
+ static bool QuotePlainString(const std::string& src_utf8, std::string* dst);
+
+ // 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.
+ static bool QuoteStringForRegex(const std::string& str_utf8,
+ std::string* dst);
+
+ // 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.
+ static void GetCanonicalSandboxPath(FilePath* path);
+
+ FRIEND_TEST(MacDirAccessSandboxTest, StringEscape);
+ FRIEND_TEST(MacDirAccessSandboxTest, RegexEscape);
+ FRIEND_TEST(MacDirAccessSandboxTest, SandboxAccess);
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox);
+};
} // namespace sandbox
diff --git a/chrome/common/sandbox_mac.mm b/chrome/common/sandbox_mac.mm
index 608ba27..6ede3bf 100644
--- a/chrome/common/sandbox_mac.mm
+++ b/chrome/common/sandbox_mac.mm
@@ -69,15 +69,13 @@ bool EscapeSingleChar(char c, std::string* dst) {
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) {
+
+// static
+bool Sandbox::QuotePlainString(const std::string& src_utf8, std::string* dst) {
dst->clear();
- const char* src = str_utf8.c_str();
- int32_t length = str_utf8.length();
+ const char* src = src_utf8.c_str();
+ int32_t length = src_utf8.length();
int32_t position = 0;
while (position < length) {
UChar32 c;
@@ -108,18 +106,9 @@ bool QuotePlainString(const std::string& str_utf8, std::string* dst) {
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) {
+// static
+bool Sandbox::QuoteStringForRegex(const std::string& str_utf8,
+ std::string* dst) {
// Characters with special meanings in sandbox profile syntax.
const char regex_special_chars[] = {
'\\',
@@ -186,7 +175,9 @@ bool QuoteStringForRegex(const std::string& str_utf8, std::string* dst) {
// enable the function is also noted.
// This function is tested on the following OS versions:
// 10.5.6, 10.6.0
-void SandboxWarmup() {
+
+// static
+void Sandbox::SandboxWarmup() {
base::mac::ScopedNSAutoreleasePool scoped_pool;
{ // CGColorSpaceCreateWithName(), CGBitmapContextCreate() - 10.5.6
@@ -242,38 +233,90 @@ void SandboxWarmup() {
}
}
-// 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.";
+// static
+NSString* Sandbox::BuildAllowDirectoryAccessSandboxString(
+ const FilePath& allowed_dir,
+ SandboxVariableSubstitions* substitutions) {
+ // A whitelist is used to determine which directories can be statted
+ // This means that in the case of an /a/b/c/d/ directory, we may be able to
+ // stat the leaf directory, but not it's parent.
+ // The extension code in Chrome calls realpath() which fails if it can't call
+ // stat() on one of the parent directories in the path.
+ // The solution to this is to allow statting the parent directories themselves
+ // but not their contents. We need to add a separate rule for each parent
+ // directory.
+
+ // 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);
+
+ // Collect a list of all parent directories.
+ FilePath last_path = allowed_dir_canonical;
+ std::vector<FilePath> subpaths;
+ for (FilePath path = allowed_dir_canonical.DirName();
+ path.value() != last_path.value();
+ path = path.DirName()) {
+ subpaths.push_back(path);
+ last_path = path;
}
+
+ // Iterate through all parents and allow stat() on them explicitly.
+ NSString* sandbox_command = @"(allow file-read-metadata ";
+ for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin();
+ i != subpaths.rend();
+ ++i) {
+ std::string subdir_escaped;
+ if (!QuotePlainString(i->value(), &subdir_escaped)) {
+ LOG(FATAL) << "String quoting failed " << i->value();
+ return nil;
+ }
+
+ NSString* subdir_escaped_ns =
+ base::SysUTF8ToNSString(subdir_escaped.c_str());
+ sandbox_command =
+ [sandbox_command stringByAppendingFormat:@"(literal \"%@\")",
+ subdir_escaped_ns];
+ }
+
+ // Finally append the leaf directory. Unlike it's parents (for which only
+ // stat() should be allowed), the leaf directory needs full access.
+ (*substitutions)["ALLOWED_DIR"] =
+ SandboxSubstring(allowed_dir_canonical.value(),
+ SandboxSubstring::REGEX);
+ sandbox_command =
+ [sandbox_command
+ stringByAppendingString:@") (allow file-read* file-write*"
+ " (regex #\"@ALLOWED_DIR@\") )"];
+ return sandbox_command;
+}
+
+// Load the appropriate template for the given sandbox type.
+// Returns the template as an NSString or nil on error.
+NSString* LoadSandboxTemplate(Sandbox::SandboxProcessType sandbox_type) {
// 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;
switch (sandbox_type) {
- case SANDBOX_TYPE_RENDERER:
+ case Sandbox::SANDBOX_TYPE_RENDERER:
sandbox_config_filename = @"renderer";
break;
- case SANDBOX_TYPE_WORKER:
+ case Sandbox::SANDBOX_TYPE_WORKER:
sandbox_config_filename = @"worker";
break;
- case SANDBOX_TYPE_UTILITY:
+ case Sandbox::SANDBOX_TYPE_UTILITY:
sandbox_config_filename = @"utility";
break;
- case SANDBOX_TYPE_NACL_LOADER:
+ case Sandbox::SANDBOX_TYPE_NACL_LOADER:
// The Native Client loader is used for safeguarding the user's
// untrusted code within Native Client.
sandbox_config_filename = @"nacl_loader";
break;
default:
NOTREACHED();
- return false;
+ return nil;
}
// Read in the sandbox profile and the common prefix file.
@@ -288,7 +331,7 @@ bool EnableSandbox(SandboxProcessType sandbox_type,
if (!common_sandbox_prefix_data) {
LOG(FATAL) << "Failed to find the sandbox profile on disk "
<< [common_sandbox_prefix_path fileSystemRepresentation];
- return false;
+ return nil;
}
NSString* sandbox_profile_path =
@@ -302,74 +345,149 @@ bool EnableSandbox(SandboxProcessType sandbox_type,
if (!sandbox_data) {
LOG(FATAL) << "Failed to find the sandbox profile on disk "
<< [sandbox_profile_path fileSystemRepresentation];
- return false;
+ return nil;
}
// Prefix sandbox_data with common_sandbox_prefix_data.
- sandbox_data =
- [common_sandbox_prefix_data stringByAppendingString:sandbox_data];
+ return [common_sandbox_prefix_data stringByAppendingString:sandbox_data];
+}
+
+// Retrieve OS X version, output parameters are self explanatory.
+void GetOSVersion(bool* snow_leopard_or_higher) {
+ int32 major_version, minor_version, bugfix_version;
+ base::SysInfo::OperatingSystemVersionNumbers(&major_version,
+ &minor_version,
+ &bugfix_version);
+ *snow_leopard_or_higher =
+ (major_version > 10 || (major_version == 10 && minor_version >= 6));
+}
+
+// static
+bool Sandbox::PostProcessSandboxProfile(
+ NSString* sandbox_template,
+ NSArray* comments_to_remove,
+ SandboxVariableSubstitions& substitutions,
+ std::string *final_sandbox_profile_str) {
+ NSString* sandbox_data = [[sandbox_template copy] autorelease];
+
+ // Remove comments, e.g. ;10.6_ONLY .
+ for (NSString* to_remove in comments_to_remove) {
+ sandbox_data = [sandbox_data stringByReplacingOccurrencesOfString:to_remove
+ withString:@""];
+ }
+
+ // Split string on "@" characters.
+ std::vector<std::string> raw_sandbox_pieces;
+ if (Tokenize([sandbox_data UTF8String], "@", &raw_sandbox_pieces) == 0) {
+ LOG(FATAL) << "Bad Sandbox profile, should contain at least one token ("
+ << [sandbox_data UTF8String]
+ << ")";
+ return false;
+ }
+
+ // Iterate over string pieces and substitute variables, escaping as necessary.
+ size_t output_string_length = 0;
+ std::vector<std::string> processed_sandbox_pieces(raw_sandbox_pieces.size());
+ for (std::vector<std::string>::iterator it = raw_sandbox_pieces.begin();
+ it != raw_sandbox_pieces.end();
+ ++it) {
+ std::string new_piece;
+ SandboxVariableSubstitions::iterator replacement_it =
+ substitutions.find(*it);
+ if (replacement_it == substitutions.end()) {
+ new_piece = *it;
+ } else {
+ // Found something to substitute.
+ SandboxSubstring& replacement = replacement_it->second;
+ switch (replacement.type()) {
+ case SandboxSubstring::PLAIN:
+ new_piece = replacement.value();
+ break;
+
+ case SandboxSubstring::LITERAL:
+ QuotePlainString(replacement.value(), &new_piece);
+ break;
+
+ case SandboxSubstring::REGEX:
+ QuoteStringForRegex(replacement.value(), &new_piece);
+ break;
+ }
+ }
+ output_string_length += new_piece.size();
+ processed_sandbox_pieces.push_back(new_piece);
+ }
+
+ // Build final output string.
+ final_sandbox_profile_str->reserve(output_string_length);
+
+ for (std::vector<std::string>::iterator it = processed_sandbox_pieces.begin();
+ it != processed_sandbox_pieces.end();
+ ++it) {
+ final_sandbox_profile_str->append(*it);
+ }
+ return true;
+}
+
+
+// Turns on the OS X sandbox for this process.
+
+// static
+bool Sandbox::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.";
+ }
+
+ NSString* sandbox_data = LoadSandboxTemplate(sandbox_type);
+ if (!sandbox_data) {
+ return false;
+ }
+
+ SandboxVariableSubstitions substitutions;
+ if (!allowed_dir.empty()) {
+ // Add the sandbox commands necessary to access the given directory.
+ // Note: this function must be called before PostProcessSandboxProfile()
+ // since the string it inserts contains variables that need substitution.
+ NSString* allowed_dir_sandbox_command =
+ BuildAllowDirectoryAccessSandboxString(allowed_dir, &substitutions);
+
+ if (allowed_dir_sandbox_command) { // May be nil if function fails.
+ sandbox_data = [sandbox_data
+ stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS"
+ withString:allowed_dir_sandbox_command];
+ }
+ }
+
+ NSMutableArray* tokens_to_remove = [NSMutableArray array];
// Enable verbose logging if enabled on the command line. (See common.sb
// for details).
const CommandLine *command_line = CommandLine::ForCurrentProcess();
bool enable_logging =
- command_line->HasSwitch(switches::kEnableSandboxLogging);
+ command_line->HasSwitch(switches::kEnableSandboxLogging);;
if (enable_logging) {
- sandbox_data = [sandbox_data
- stringByReplacingOccurrencesOfString:@";ENABLE_LOGGING"
- withString:@""];
+ [tokens_to_remove addObject:@";ENABLE_LOGGING"];
}
- // Get the OS version.
- int32 major_version, minor_version, bugfix_version;
- base::SysInfo::OperatingSystemVersionNumbers(&major_version,
- &minor_version, &bugfix_version);
- bool snow_leopard_or_higher =
- (major_version > 10 || (major_version == 10 && minor_version >= 6));
+ bool snow_leopard_or_higher;
+ GetOSVersion(&snow_leopard_or_higher);
// Without this, the sandbox will print a message to the system log every
// time it denies a request. This floods the console with useless spew. The
// (with no-log) syntax is only supported on 10.6+
if (snow_leopard_or_higher && !enable_logging) {
- sandbox_data = [sandbox_data
- stringByReplacingOccurrencesOfString:@"DISABLE_SANDBOX_DENIAL_LOGGING"
- withString:@"(with no-log)"];
+ substitutions["DISABLE_SANDBOX_DENIAL_LOGGING"] =
+ SandboxSubstring("(with no-log)");
} else {
- sandbox_data = [sandbox_data
- stringByReplacingOccurrencesOfString:@"DISABLE_SANDBOX_DENIAL_LOGGING"
- 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];
-
+ substitutions["DISABLE_SANDBOX_DENIAL_LOGGING"] = SandboxSubstring("");
}
if (snow_leopard_or_higher) {
// 10.6-only Sandbox rules.
- sandbox_data = [sandbox_data
- stringByReplacingOccurrencesOfString:@";10.6_ONLY"
- withString:@""];
+ [tokens_to_remove addObject:@";10.6_ONLY"];
// 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
@@ -381,24 +499,25 @@ bool EnableSandbox(SandboxProcessType sandbox_type,
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) {
+ substitutions["USER_HOMEDIR_AS_LITERAL"] =
+ SandboxSubstring(home_dir_canonical.value(),
+ SandboxSubstring::LITERAL);
+ } else {
// Sandbox rules only for versions before 10.6.
- sandbox_data = [sandbox_data
- stringByReplacingOccurrencesOfString:@";BEFORE_10.6"
- withString:@""];
+ [tokens_to_remove addObject:@";BEFORE_10.6"];
+ }
+
+ // All information needed to assemble the final profile has been collected.
+ // Merge it all together.
+ std::string final_sandbox_profile_str;
+ if (!PostProcessSandboxProfile(sandbox_data, tokens_to_remove, substitutions,
+ &final_sandbox_profile_str)) {
+ return false;
}
+ // Initialize sandbox.
char* error_buff = NULL;
- int error = sandbox_init([sandbox_data UTF8String], 0, &error_buff);
+ int error = sandbox_init(final_sandbox_profile_str.c_str(), 0, &error_buff);
bool success = (error == 0 && error_buff == NULL);
LOG_IF(FATAL, !success) << "Failed to initialize sandbox: "
<< error
@@ -408,7 +527,8 @@ bool EnableSandbox(SandboxProcessType sandbox_type,
return success;
}
-void GetCanonicalSandboxPath(FilePath* path) {
+// static
+void Sandbox::GetCanonicalSandboxPath(FilePath* path) {
int fd = HANDLE_EINTR(open(path->value().c_str(), O_RDONLY));
if (fd < 0) {
PLOG(FATAL) << "GetCanonicalSandboxPath() failed for: "
diff --git a/chrome/common/sandbox_mac_diraccess_unittest.mm b/chrome/common/sandbox_mac_diraccess_unittest.mm
index 5804361..fed540d 100644
--- a/chrome/common/sandbox_mac_diraccess_unittest.mm
+++ b/chrome/common/sandbox_mac_diraccess_unittest.mm
@@ -18,18 +18,16 @@ extern "C" {
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.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";
+static const char* kDeniedSuffix = "_denied";
+
+} // namespace
+
+// Tests need to be in the same namespace as the sandbox::Sandbox class to be
+// useable with FRIEND_TEST() declaration.
+namespace sandbox {
class MacDirAccessSandboxTest : public base::MultiProcessTest {
public:
@@ -47,8 +45,6 @@ class MacDirAccessSandboxTest : public base::MultiProcessTest {
};
TEST_F(MacDirAccessSandboxTest, StringEscape) {
- using sandbox::QuotePlainString;
-
const struct string_escape_test_data {
const char* to_escape;
const char* escaped;
@@ -64,14 +60,12 @@ TEST_F(MacDirAccessSandboxTest, StringEscape) {
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_TRUE(Sandbox::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;
@@ -89,24 +83,25 @@ TEST_F(MacDirAccessSandboxTest, RegexEscape) {
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));
+ EXPECT_FALSE(Sandbox::QuoteStringForRegex(fail_string, &out));
+ EXPECT_TRUE(Sandbox::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));
+ EXPECT_TRUE(Sandbox::QuoteStringForRegex("}", &out)); // } == 0x7D == 125
+ EXPECT_FALSE(Sandbox::QuoteStringForRegex("~", &out)); // ~ == 0x7E == 126
+ EXPECT_FALSE(
+ Sandbox::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));
+ EXPECT_TRUE(Sandbox::QuoteStringForRegex(in, &out));
std::string expected("^");
expected.append(regex_cases[i].escaped);
expected.append(kSandboxEscapeSuffix);
@@ -125,7 +120,7 @@ TEST_F(MacDirAccessSandboxTest, RegexEscape) {
expected.append(kSandboxEscapeSuffix);
std::string out;
- EXPECT_TRUE(QuoteStringForRegex(in_utf8, &out));
+ EXPECT_TRUE(Sandbox::QuoteStringForRegex(in_utf8, &out));
EXPECT_EQ(expected, out);
}
@@ -143,14 +138,15 @@ class ScopedDirectoryDelete {
typedef scoped_ptr_malloc<FilePath, ScopedDirectoryDelete> ScopedDirectory;
-// Crashy, http://crbug.com/56765.
-TEST_F(MacDirAccessSandboxTest, DISABLED_SandboxAccess) {
+TEST_F(MacDirAccessSandboxTest, SandboxAccess) {
+ using file_util::CreateDirectory;
+
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);
+ Sandbox::GetCanonicalSandboxPath(&tmp_dir);
ScopedDirectory cleanup(&tmp_dir);
const char* sandbox_dir_cases[] = {
@@ -162,8 +158,18 @@ TEST_F(MacDirAccessSandboxTest, DISABLED_SandboxAccess) {
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));
+ ASSERT_TRUE(CreateDirectory(sandbox_dir));
ScopedDirectory cleanup_sandbox(&sandbox_dir);
+
+ // Create a sibling directory of the sandbox dir, whose name has sandbox dir
+ // as a substring but to which access is denied.
+ std::string sibling_sandbox_dir_name_denied =
+ std::string(sandbox_dir_cases[i]) + kDeniedSuffix;
+ FilePath sibling_sandbox_dir = tmp_dir.Append(
+ sibling_sandbox_dir_name_denied.c_str());
+ ASSERT_TRUE(CreateDirectory(sibling_sandbox_dir));
+ ScopedDirectory cleanup_sandbox_sibling(&sibling_sandbox_dir);
+
EXPECT_TRUE(CheckSandbox(sandbox_dir.value()));
}
}
@@ -173,29 +179,36 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
if (!sandbox_allowed_dir)
return -1;
- // Build up a sandbox profile that only allows access to DIR_TO_ALLOW_ACCESS.
+ // Build up a sandbox profile that only allows access to a single directory.
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\"))";
+ ";ENABLE_DIRECTORY_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;
+ Sandbox::SandboxVariableSubstitions substitutions;
+ NSString* allow_dir_sandbox_code =
+ Sandbox::BuildAllowDirectoryAccessSandboxString(
+ FilePath(sandbox_allowed_dir),
+ &substitutions);
+ sandbox_profile = [sandbox_profile
+ stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS"
+ withString:allow_dir_sandbox_code];
+
+ std::string final_sandbox_profile_str;
+ if (!Sandbox::PostProcessSandboxProfile(sandbox_profile,
+ [NSArray array],
+ substitutions,
+ &final_sandbox_profile_str)) {
+ LOG(ERROR) << "Call to PostProcessSandboxProfile() failed";
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);
+ int error = sandbox_init(final_sandbox_profile_str.c_str(), 0, &error_buff);
if (error == -1) {
LOG(ERROR) << "Failed to Initialize Sandbox: " << error_buff;
return -1;
@@ -223,8 +236,9 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_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();
+ FilePath allowed_parent_dir = allowed_dir_path.DirName();
std::string tricky_filename = basename.value() + "123";
- FilePath denied_file2 = allowed_dir_path.DirName().Append(tricky_filename);
+ FilePath denied_file2 = allowed_parent_dir.Append(tricky_filename);
if (open(allowed_file.value().c_str(), O_WRONLY | O_CREAT) <= 0) {
PLOG(ERROR) << "Sandbox overly restrictive: failed to write ("
@@ -233,6 +247,43 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
return -1;
}
+ // Test that we deny access to a sibling of the sandboxed directory whose
+ // name has the sandboxed directory name as a substring. e.g. if the sandbox
+ // directory is /foo/baz then test /foo/baz_denied.
+ {
+ struct stat tmp_stat_info;
+ std::string denied_sibling =
+ std::string(sandbox_allowed_dir) + kDeniedSuffix;
+ if (stat(denied_sibling.c_str(), &tmp_stat_info) > 0) {
+ PLOG(ERROR) << "Sandbox breach: was able to stat ("
+ << denied_sibling.c_str()
+ << ")";
+ return -1;
+ }
+ }
+
+ // Test that we can stat parent directories of the "allowed" directory.
+ {
+ struct stat tmp_stat_info;
+ if (stat(allowed_parent_dir.value().c_str(), &tmp_stat_info) != 0) {
+ PLOG(ERROR) << "Sandbox overly restrictive: unable to stat ("
+ << allowed_parent_dir.value()
+ << ")";
+ return -1;
+ }
+ }
+
+ // Test that we can't stat files outside the "allowed" directory.
+ {
+ struct stat tmp_stat_info;
+ if (stat(denied_file1.value().c_str(), &tmp_stat_info) > 0) {
+ PLOG(ERROR) << "Sandbox breach: was able to stat ("
+ << denied_file1.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()
@@ -250,4 +301,4 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
return 0;
}
-} // namespace
+} // namespace sandbox
diff --git a/chrome/common/sandbox_mac_fontloading_unittest.mm b/chrome/common/sandbox_mac_fontloading_unittest.mm
index 834fc0b..17f4a4a 100644
--- a/chrome/common/sandbox_mac_fontloading_unittest.mm
+++ b/chrome/common/sandbox_mac_fontloading_unittest.mm
@@ -16,6 +16,7 @@
namespace {
using sandboxtest::MacSandboxTest;
+using sandbox::Sandbox;
bool CGFontFromFontContainer(ATSFontContainerRef container, CGFontRef* out) {
// Count the number of fonts that were loaded.
@@ -91,16 +92,11 @@ bool FontLoadingTestCase::BeforeSandboxInit() {
return false;
}
- if (!font_shmem_->Create("", false, false, font_data_length_)) {
+ if (!font_shmem_->CreateAndMapAnonymous(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";
@@ -126,32 +122,32 @@ bool FontLoadingTestCase::SandboxedTest() {
// Unload the font container when done.
ScopedFontContainer scoped_unloader(font_container);
- CGFontRef font_ref;
- if (!CGFontFromFontContainer(font_container, &font_ref)) {
+ CGFontRef cg_font_ref;
+ if (!CGFontFromFontContainer(font_container, &cg_font_ref)) {
LOG(ERROR) << "CGFontFromFontContainer failed";
return false;
}
- if (!font_ref) {
+ if (!cg_font_ref) {
LOG(ERROR) << "Got NULL CGFontRef";
return false;
}
- base::mac::ScopedCFTypeRef<CGFontRef> cgfont;
- cgfont.reset(font_ref);
+ base::mac::ScopedCFTypeRef<CGFontRef> cgfont(cg_font_ref);
+
+ CTFontRef ct_font_ref =
+ CTFontCreateWithGraphicsFont(cgfont.get(), 16.0, NULL, NULL);
+ base::mac::ScopedCFTypeRef<CTFontRef> ctfont(ct_font_ref);
- const NSFont* nsfont = reinterpret_cast<const NSFont*>(
- CTFontCreateWithGraphicsFont(cgfont.get(), 16.0,
- NULL, NULL));
- if (!nsfont) {
+ if (!ct_font_ref) {
LOG(ERROR) << "CTFontCreateWithGraphicsFont() failed";
return false;
}
// Do something with the font to make sure it's loaded.
- CGFloat cap_height = [nsfont capHeight];
+ CGFloat cap_height = CTFontGetCapHeight(ct_font_ref);
if (cap_height <= 0.0) {
- LOG(ERROR) << "Got bad value for [NSFont capHeight] " << cap_height;
+ LOG(ERROR) << "Got bad value for CTFontGetCapHeight " << cap_height;
return false;
}
@@ -174,7 +170,7 @@ TEST_F(MacSandboxTest, FontLoadingTest) {
file_util::WriteFileDescriptor(fileno(temp_file),
static_cast<const char *>(font_data.memory()), font_data_size);
- ASSERT_TRUE(RunTestInSandbox(sandbox::SANDBOX_TYPE_RENDERER,
+ 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));
diff --git a/chrome/common/sandbox_mac_unittest_helper.h b/chrome/common/sandbox_mac_unittest_helper.h
index 960a4cf..674b246 100644
--- a/chrome/common/sandbox_mac_unittest_helper.h
+++ b/chrome/common/sandbox_mac_unittest_helper.h
@@ -50,7 +50,7 @@ class MacSandboxTest : public base::MultiProcessTest {
// 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,
+ bool RunTestInSandbox(sandbox::Sandbox::SandboxProcessType sandbox_type,
const char* test_name,
const char* test_data);
diff --git a/chrome/common/sandbox_mac_unittest_helper.mm b/chrome/common/sandbox_mac_unittest_helper.mm
index 007530e..4e885b5 100644
--- a/chrome/common/sandbox_mac_unittest_helper.mm
+++ b/chrome/common/sandbox_mac_unittest_helper.mm
@@ -16,6 +16,8 @@ extern "C" {
#include "chrome/common/sandbox_mac.h"
#include "testing/multiprocess_func_list.h"
+using sandbox::Sandbox;
+
namespace {
const char* kSandboxTypeKey = "CHROMIUM_SANDBOX_SANDBOX_TYPE";
@@ -52,10 +54,10 @@ 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;
+ 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),
+ if (!RunTestInSandbox(static_cast<Sandbox::SandboxProcessType>(i),
test_name, test_data)) {
LOG(ERROR) << "Sandboxed test (" << test_name << ")" <<
"Failed in sandbox type " << i <<
@@ -66,7 +68,7 @@ bool MacSandboxTest:: RunTestInAllSandboxTypes(const char* test_name,
return true;
}
-bool MacSandboxTest::RunTestInSandbox(sandbox::SandboxProcessType sandbox_type,
+bool MacSandboxTest::RunTestInSandbox(Sandbox::SandboxProcessType sandbox_type,
const char* test_name,
const char* test_data) {
std::stringstream s;
@@ -116,8 +118,8 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_test_runner) {
LOG(ERROR) << "Sandbox type not specified";
return -1;
}
- sandbox::SandboxProcessType sandbox_type =
- static_cast<sandbox::SandboxProcessType>(atoi(sandbox_type_str));
+ 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";
@@ -141,9 +143,9 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_test_runner) {
return -1;
}
- sandbox::SandboxWarmup();
+ Sandbox::SandboxWarmup();
- if (!sandbox::EnableSandbox(sandbox_type, FilePath())) {
+ if (!Sandbox::EnableSandbox(sandbox_type, FilePath())) {
LOG(ERROR) << "Failed to initialize sandbox " << sandbox_type;
return -1;
}
diff --git a/chrome/common/sandbox_policy.cc b/chrome/common/sandbox_policy.cc
index f97da8a..0ab7563 100644
--- a/chrome/common/sandbox_policy.cc
+++ b/chrome/common/sandbox_policy.cc
@@ -8,7 +8,8 @@
#include "app/win_util.h"
#include "base/command_line.h"
-#include "base/debug_util.h"
+#include "base/debug/debugger.h"
+#include "base/debug/trace_event.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
@@ -16,7 +17,6 @@
#include "base/stringprintf.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
-#include "base/trace_event.h"
#include "base/win/windows_version.h"
#include "chrome/common/child_process_info.h"
#include "chrome/common/chrome_constants.h"
@@ -513,7 +513,7 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
// 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->AppendArg(StringPrintf("/prefetch:%d", type));
+ cmd_line->AppendArg(base::StringPrintf("/prefetch:%d", type));
if (!in_sandbox) {
base::LaunchApp(*cmd_line, false, false, &process);
@@ -579,7 +579,7 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
// 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);
+ base::debug::SpawnDebuggerOnProcess(target.dwProcessId);
return process;
}
diff --git a/chrome/common/security_filter_peer.cc b/chrome/common/security_filter_peer.cc
index 9b0815b..3be8864 100644
--- a/chrome/common/security_filter_peer.cc
+++ b/chrome/common/security_filter_peer.cc
@@ -53,7 +53,7 @@ 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(
+ std::string html = base::StringPrintf(
"<html><meta charset='UTF-8'>"
"<body style='background-color:#990000;color:white;'>"
"%s</body></html>",
@@ -90,10 +90,6 @@ void SecurityFilterPeer::OnCompletedRequest(const URLRequestStatus& status,
NOTREACHED();
}
-GURL SecurityFilterPeer::GetURLForDebugging() const {
- return original_peer_->GetURLForDebugging();
-}
-
// static
void ProcessResponseInfo(
const webkit_glue::ResourceResponseInfo& info_in,
diff --git a/chrome/common/security_filter_peer.h b/chrome/common/security_filter_peer.h
index 8365ebd..2559bf3 100644
--- a/chrome/common/security_filter_peer.h
+++ b/chrome/common/security_filter_peer.h
@@ -44,7 +44,6 @@ class SecurityFilterPeer : public webkit_glue::ResourceLoaderBridge::Peer {
virtual void OnCompletedRequest(const URLRequestStatus& status,
const std::string& security_info,
const base::Time& completion_time);
- virtual GURL GetURLForDebugging() const;
protected:
SecurityFilterPeer(webkit_glue::ResourceLoaderBridge* resource_loader_bridge,
diff --git a/chrome/common/service_process_util.cc b/chrome/common/service_process_util.cc
index f636f2b..489610a 100644
--- a/chrome/common/service_process_util.cc
+++ b/chrome/common/service_process_util.cc
@@ -212,8 +212,8 @@ bool ServiceProcessState::CreateSharedData() {
return false;
uint32 alloc_size = sizeof(ServiceProcessSharedData);
- if (!shared_mem_service_data->Create(GetServiceProcessSharedMemName(), false,
- true, alloc_size))
+ if (!shared_mem_service_data->CreateNamed(GetServiceProcessSharedMemName(),
+ true, alloc_size))
return false;
if (!shared_mem_service_data->Map(alloc_size))
diff --git a/chrome/common/speech_input_result.h b/chrome/common/speech_input_result.h
new file mode 100644
index 0000000..2807412
--- /dev/null
+++ b/chrome/common/speech_input_result.h
@@ -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.
+
+#ifndef CHROME_COMMON_SPEECH_INPUT_RESULT_H_
+#define CHROME_COMMON_SPEECH_INPUT_RESULT_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+
+namespace speech_input {
+
+struct SpeechInputResultItem {
+ string16 utterance;
+ double confidence;
+
+ SpeechInputResultItem()
+ : confidence(0.0) {
+ }
+
+ SpeechInputResultItem(const string16 utterance_value, double confidence_value)
+ : utterance(utterance_value),
+ confidence(confidence_value) {
+ }
+};
+
+typedef std::vector<SpeechInputResultItem> SpeechInputResultArray;
+
+} // namespace speech_input
+
+#endif // CHROME_COMMON_SPEECH_INPUT_RESULT_H_
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 1c65a66..427c933 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -1,3 +1,4 @@
+
// 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.
@@ -11,6 +12,7 @@ namespace chrome {
const char kAboutScheme[] = "about";
const char kBlobScheme[] = "blob";
+const char kChromeDevToolsScheme[] = "chrome-devtools";
const char kChromeInternalScheme[] = "chrome-internal";
const char kChromeUIScheme[] = "chrome";
const char kDataScheme[] = "data";
@@ -38,6 +40,7 @@ const char* kSavableSchemes[] = {
kFileScheme,
kFtpScheme,
kExtensionScheme,
+ kChromeDevToolsScheme,
kChromeUIScheme,
NULL
};
@@ -46,6 +49,7 @@ const char kAboutAboutURL[] = "about:about";
const char kAboutAppCacheInternalsURL[] = "about:appcache-internals";
const char kAboutBlankURL[] = "about:blank";
const char kAboutCacheURL[] = "about:cache";
+const char kAboutConflicts[] = "about:conflicts";
const char kAboutCrashURL[] = "about:crash";
const char kAboutCreditsURL[] = "about:credits";
const char kAboutDNSURL[] = "about:dns";
@@ -71,8 +75,9 @@ const char kChromeUIAboutURL[] = "chrome://settings/about";
const char kChromeUIAppLauncherURL[] = "chrome://newtab/#mode=app-launcher";
const char kChromeUIBookmarksURL[] = "chrome://bookmarks/";
const char kChromeUIBugReportURL[] = "chrome://bugreport/";
+const char kChromeUIConflictsURL[] = "chrome://conflicts/";
const char kChromeUIConstrainedHTMLTestURL[] = "chrome://constrained-test/";
-const char kChromeUIDevToolsURL[] = "chrome://devtools/";
+const char kChromeUIDevToolsURL[] = "chrome-devtools://devtools/";
const char kChromeUIDownloadsURL[] = "chrome://downloads/";
const char kChromeUIExtensionsURL[] = "chrome://extensions/";
const char kChromeUIFavIconURL[] = "chrome://favicon/";
@@ -85,10 +90,12 @@ const char kChromeUINewTabURL[] = "chrome://newtab";
const char kChromeUIPluginsURL[] = "chrome://plugins/";
const char kChromeUIPrintURL[] = "chrome://print/";
const char kChromeUISettingsURL[] = "chrome://settings/";
+const char kChromeUITextfieldsURL[] = "chrome://textfields/";
#if defined(OS_CHROMEOS)
const char kChromeUIFileBrowseURL[] = "chrome://filebrowse/";
const char kChromeUIImageBurnerURL[] = "chrome://imageburner/";
+const char kChromeUIKeyboardOverlayURL[] = "chrome://keyboardoverlay/";
const char kChromeUIMediaplayerURL[] = "chrome://mediaplayer/";
const char kChromeUIMobileSetupURL[] = "chrome://mobilesetup/";
const char kChromeUIRegisterPageURL[] = "chrome://register/";
@@ -99,6 +106,7 @@ const char kChromeUISystemInfoURL[] = "chrome://system/";
// Keep this list sorted please.
const char kChromeUIBookmarksHost[] = "bookmarks";
const char kChromeUIBugReportHost[] = "bugreport";
+const char kChromeUIConflictsHost[] = "conflicts";
const char kChromeUIDevToolsHost[] = "devtools";
const char kChromeUIDialogHost[] = "dialog";
const char kChromeUIDownloadsHost[] = "downloads";
@@ -119,12 +127,14 @@ const char kChromeUIResourcesHost[] = "resources";
const char kChromeUIScreenshotPath[] = "screenshots";
const char kChromeUISettingsHost[] = "settings";
const char kChromeUISyncResourcesHost[] = "syncresources";
+const char kChromeUITextfieldsHost[] = "textfields";
const char kChromeUIThemePath[] = "theme";
const char kChromeUIThumbnailPath[] = "thumb";
#if defined(OS_CHROMEOS)
const char kChromeUIFileBrowseHost[] = "filebrowse";
const char kChromeUIImageBurnerHost[] = "imageburner";
+const char kChromeUIKeyboardOverlayHost[] = "keyboardoverlay";
const char kChromeUIMediaplayerHost[] = "mediaplayer";
const char kChromeUIMobileSetupHost[] = "mobilesetup";
const char kChromeUIRegisterPageHost[] = "register";
@@ -135,6 +145,8 @@ const char kChromeUIWrenchMenu[] = "wrench-menu";
const char kChromeUINetworkMenu[] = "network-menu";
#endif
+const char kUnreachableWebDataURL[] = "chrome://chromewebdata/";
+
const char kAppCacheViewInternalsURL[] = "chrome://appcache-internals/";
const char kBlobViewInternalsURL[] = "chrome://blob-internals/";
@@ -165,6 +177,7 @@ const char kSystemOptionsSubPage[] = "system";
void RegisterChromeSchemes() {
// Don't need "chrome-internal" which was used in old versions of Chrome for
// the new tab page.
+ url_util::AddStandardScheme(kChromeDevToolsScheme);
url_util::AddStandardScheme(kChromeUIScheme);
url_util::AddStandardScheme(kGearsScheme);
url_util::AddStandardScheme(kExtensionScheme);
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index e11e5b5..05e32e6 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -13,6 +13,7 @@ namespace chrome {
// Canonical schemes you can use as input to GURL.SchemeIs().
extern const char kAboutScheme[];
extern const char kBlobScheme[];
+extern const char kChromeDevToolsScheme[];
extern const char kChromeInternalScheme[];
extern const char kChromeUIScheme[]; // The scheme used for DOMUIs.
extern const char kCrosScheme[]; // The scheme used for ChromeOS.
@@ -40,6 +41,7 @@ extern const char kAboutAboutURL[];
extern const char kAboutAppCacheInternalsURL[];
extern const char kAboutBlankURL[];
extern const char kAboutBrowserCrash[];
+extern const char kAboutConflicts[];
extern const char kAboutCacheURL[];
extern const char kAboutCrashURL[];
extern const char kAboutCreditsURL[];
@@ -64,6 +66,7 @@ extern const char kChromeUIAboutURL[];
extern const char kChromeUIAppLauncherURL[];
extern const char kChromeUIBookmarksURL[];
extern const char kChromeUIBugReportURL[];
+extern const char kChromeUIConflictsURL[];
extern const char kChromeUIConstrainedHTMLTestURL[];
extern const char kChromeUIDevToolsURL[];
extern const char kChromeUIDownloadsURL[];
@@ -78,10 +81,12 @@ extern const char kChromeUINewTabURL[];
extern const char kChromeUIPluginsURL[];
extern const char kChromeUIPrintURL[];
extern const char kChromeUISettingsURL[];
+extern const char kChromeUITextfieldsURL[];
#if defined(OS_CHROMEOS)
extern const char kChromeUIFileBrowseURL[];
extern const char kChromeUIImageBurnerURL[];
+extern const char kChromeUIKeyboardOverlayURL[];
extern const char kChromeUIMediaplayerURL[];
extern const char kChromeUIMobileSetupURL[];
extern const char kChromeUIRegisterPageURL[];
@@ -93,6 +98,7 @@ extern const char kChromeUISystemInfoURL[];
// above.
extern const char kChromeUIBookmarksHost[];
extern const char kChromeUIBugReportHost[];
+extern const char kChromeUIConflictsHost[];
extern const char kChromeUIDevToolsHost[];
extern const char kChromeUIDialogHost[];
extern const char kChromeUIDownloadsHost[];
@@ -101,7 +107,6 @@ extern const char kChromeUIFavIconHost[];
extern const char kChromeUIFlagsHost[];
extern const char kChromeUIHistory2Host[];
extern const char kChromeUIHistoryHost[];
-extern const char kChromeUIInspectorHost[];
extern const char kChromeUIKeyboardHost[];
extern const char kChromeUINetInternalsHost[];
extern const char kChromeUINewTabHost[];
@@ -113,12 +118,14 @@ extern const char kChromeUIResourcesHost[];
extern const char kChromeUIScreenshotPath[];
extern const char kChromeUISettingsHost[];
extern const char kChromeUISyncResourcesHost[];
+extern const char kChromeUITextfieldsHost[];
extern const char kChromeUIThemePath[];
extern const char kChromeUIThumbnailPath[];
#if defined(OS_CHROMEOS)
extern const char kChromeUIFileBrowseHost[];
extern const char kChromeUIImageBurnerHost[];
+extern const char kChromeUIKeyboardOverlayHost[];
extern const char kChromeUIMediaplayerHost[];
extern const char kChromeUIMobileSetupHost[];
extern const char kChromeUIRegisterPageHost[];
@@ -129,6 +136,9 @@ extern const char kChromeUIWrenchMenu[];
extern const char kChromeUINetworkMenu[];
#endif
+// Special URL used to start a navigation to an error page.
+extern const char kUnreachableWebDataURL[];
+
// AppCache related URL.
extern const char kAppCacheViewInternalsURL[];
diff --git a/chrome/common/view_types.h b/chrome/common/view_types.h
index 7a1caf0..2d9c539 100644
--- a/chrome/common/view_types.h
+++ b/chrome/common/view_types.h
@@ -21,7 +21,6 @@ class ViewType {
DEV_TOOLS_UI,
INTERSTITIAL_PAGE,
NOTIFICATION,
- HTML_DIALOG_UI,
};
// Constant strings corresponding to the Type enumeration values. Used
diff --git a/chrome/common/webkit_param_traits.cc b/chrome/common/webkit_param_traits.cc
index 26465dd..909d7fd 100644
--- a/chrome/common/webkit_param_traits.cc
+++ b/chrome/common/webkit_param_traits.cc
@@ -40,7 +40,8 @@ void ParamTraits<WebKit::WebRect>::Log(const param_type& p, std::string* l) {
l->append(")");
}
-void ParamTraits<WebKit::WebScreenInfo>::Write(Message* m, const param_type& p) {
+void ParamTraits<WebKit::WebScreenInfo>::Write(Message* m,
+ const param_type& p) {
WriteParam(m, p.depth);
WriteParam(m, p.depthPerComponent);
WriteParam(m, p.isMonochrome);
@@ -101,8 +102,8 @@ void ParamTraits<WebKit::WebFindOptions>::Log(const param_type& p,
void ParamTraits<WebKit::WebCache::ResourceTypeStat>::Log(
const param_type& p, std::string* l) {
- l->append(StringPrintf("%" PRIuS " %" PRIuS " %" PRIuS " %" PRIuS,
- p.count, p.size, p.liveSize, p.decodedSize));
+ l->append(base::StringPrintf("%" PRIuS " %" PRIuS " %" PRIuS " %" PRIuS,
+ p.count, p.size, p.liveSize, p.decodedSize));
}
void ParamTraits<WebKit::WebMediaPlayerAction>::Write(Message* m,
diff --git a/chrome/common/webmessageportchannel_impl.cc b/chrome/common/webmessageportchannel_impl.cc
index 888ab78..b7a9388 100644
--- a/chrome/common/webmessageportchannel_impl.cc
+++ b/chrome/common/webmessageportchannel_impl.cc
@@ -69,8 +69,8 @@ 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);
+ scoped_refptr<WebMessagePortChannelImpl> webchannel(
+ static_cast<WebMessagePortChannelImpl*>(channel));
Entangle(webchannel);
}