summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-10 10:08:57 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-10 10:08:57 +0000
commitadd184df7cdf49062f469156018ff069a8d36f56 (patch)
tree3bbf4ef3feaf617a77c474a4ffbc52bd8d6214a3 /chrome_frame
parentab100318a067963f3dcadd2d4343a60f5c1526ca (diff)
downloadchromium_src-add184df7cdf49062f469156018ff069a8d36f56.zip
chromium_src-add184df7cdf49062f469156018ff069a8d36f56.tar.gz
chromium_src-add184df7cdf49062f469156018ff069a8d36f56.tar.bz2
Adding FieldTrial support for Chrome Frame to allow measurement of startup time improvements from delaying Chrome shutdown.
The other half of http://crrev.com/124942 BUG=98506 TEST=NONE Review URL: http://codereview.chromium.org/9600011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126024 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/chrome_frame_automation.cc55
-rw-r--r--chrome_frame/chrome_frame_automation.h29
-rw-r--r--chrome_frame/chrome_frame_plugin.h5
-rw-r--r--chrome_frame/chrome_launcher.cc1
-rw-r--r--chrome_frame/chrome_tab.cc16
-rw-r--r--chrome_frame/metrics_service.cc41
-rw-r--r--chrome_frame/metrics_service.h9
-rw-r--r--chrome_frame/test/automation_client_mock.cc10
-rw-r--r--chrome_frame/test/chrome_frame_automation_mock.h2
-rw-r--r--chrome_frame/test/proxy_factory_mock.cc2
-rw-r--r--chrome_frame/test/run_all_unittests.cc5
11 files changed, 132 insertions, 43 deletions
diff --git a/chrome_frame/chrome_frame_automation.cc b/chrome_frame/chrome_frame_automation.cc
index c7f144f..147cdee 100644
--- a/chrome_frame/chrome_frame_automation.cc
+++ b/chrome_frame/chrome_frame_automation.cc
@@ -14,6 +14,7 @@
#include "base/file_version_info.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/metrics/field_trial.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_util.h"
@@ -34,12 +35,20 @@
#include "chrome_frame/utils.h"
#include "ui/base/ui_base_switches.h"
+namespace {
+
#ifdef NDEBUG
int64 kAutomationServerReasonableLaunchDelay = 1000; // in milliseconds
#else
int64 kAutomationServerReasonableLaunchDelay = 1000 * 10;
#endif
+const char kChromeShutdownDelaySeconds[] = "30";
+const char kWithDelayFieldTrialName[] = "WithShutdownDelay";
+const char kNoDelayFieldTrialName[] = "NoShutdownDelay";
+
+} // namespace
+
class ChromeFrameAutomationProxyImpl::TabProxyNotificationMessageFilter
: public IPC::ChannelProxy::MessageFilter {
public:
@@ -291,6 +300,10 @@ void AutomationProxyCacheEntry::CreateProxy(ChromeFrameLaunchParams* params,
if (IsAccessibleMode())
command_line->AppendSwitch(switches::kForceRendererAccessibility);
+ if (params->send_shutdown_delay_switch())
+ command_line->AppendSwitchASCII(switches::kChromeFrameShutdownDelay,
+ kChromeShutdownDelaySeconds);
+
DVLOG(1) << "Profile path: " << params->profile_path().value();
command_line->AppendSwitchPath(switches::kUserDataDir,
params->profile_path());
@@ -335,9 +348,19 @@ void AutomationProxyCacheEntry::CreateProxy(ChromeFrameLaunchParams* params,
if (launch_result_ == AUTOMATION_SUCCESS) {
UMA_HISTOGRAM_TIMES(
"ChromeFrame.AutomationServerLaunchSuccessTime", delta);
+ UMA_HISTOGRAM_TIMES(
+ base::FieldTrial::MakeName(
+ "ChromeFrame.AutomationServerLaunchSuccessTime",
+ "ChromeShutdownDelay"),
+ delta);
} else {
UMA_HISTOGRAM_TIMES(
"ChromeFrame.AutomationServerLaunchFailedTime", delta);
+ UMA_HISTOGRAM_TIMES(
+ base::FieldTrial::MakeName(
+ "ChromeFrame.AutomationServerLaunchFailedTime",
+ "ChromeShutdownDelay"),
+ delta);
}
UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.LaunchResult",
@@ -526,7 +549,9 @@ ChromeFrameAutomationClient::ChromeFrameAutomationClient()
url_fetcher_(NULL),
url_fetcher_flags_(PluginUrlRequestManager::NOT_THREADSAFE),
navigate_after_initialization_(false),
- route_all_top_level_navigations_(false) {
+ route_all_top_level_navigations_(false),
+ send_shutdown_delay_switch_(true) {
+ InitializeFieldTrials();
}
ChromeFrameAutomationClient::~ChromeFrameAutomationClient() {
@@ -665,7 +690,8 @@ bool ChromeFrameAutomationClient::InitiateNavigation(
FilePath profile_path;
chrome_launch_params_ = new ChromeFrameLaunchParams(parsed_url,
referrer_gurl, profile_path, L"", SimpleResourceLoader::GetLanguage(),
- false, false, route_all_top_level_navigations_);
+ false, false, route_all_top_level_navigations_,
+ send_shutdown_delay_switch_);
} else {
chrome_launch_params_->set_referrer(referrer_gurl);
chrome_launch_params_->set_url(parsed_url);
@@ -1001,6 +1027,31 @@ bool ChromeFrameAutomationClient::ProcessUrlRequestMessage(TabProxy* tab,
return true;
}
+void ChromeFrameAutomationClient::InitializeFieldTrials() {
+ static base::FieldTrial* trial = NULL;
+ if (!trial) {
+ // Do one-time initialization of the field trial here.
+ // TODO(robertshield): End the field trial before March 7th 2013.
+ scoped_refptr<base::FieldTrial> new_trial = new base::FieldTrial(
+ "ChromeShutdownDelay", 1000, kWithDelayFieldTrialName, 2013, 3, 7);
+
+ // Be consistent for this client. Note that this will only have an effect
+ // once the client id is persisted. See http://crbug.com/117188
+ new_trial->UseOneTimeRandomization();
+
+ new_trial->AppendGroup(kNoDelayFieldTrialName, 500); // 50% without.
+
+ trial = new_trial.get();
+ }
+
+ // Take action depending of which group we randomly land in.
+ if (trial->group_name() == kWithDelayFieldTrialName)
+ send_shutdown_delay_switch_ = true;
+ else
+ send_shutdown_delay_switch_ = false;
+
+}
+
// These are invoked in channel's background thread.
// Cannot call any method of the activex here since it is a STA kind of being.
// By default we marshal the IPC message to the main/GUI thread and from there
diff --git a/chrome_frame/chrome_frame_automation.h b/chrome_frame/chrome_frame_automation.h
index 0115157..26c9901 100644
--- a/chrome_frame/chrome_frame_automation.h
+++ b/chrome_frame/chrome_frame_automation.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -111,13 +111,15 @@ class ChromeFrameLaunchParams : // NOLINT
const std::wstring& profile_name,
const std::wstring& language,
bool incognito, bool widget_mode,
- bool route_all_top_level_navigations)
+ bool route_all_top_level_navigations,
+ bool send_shutdown_delay_switch)
: launch_timeout_(kCommandExecutionTimeout), url_(url),
referrer_(referrer), profile_path_(profile_path),
profile_name_(profile_name), language_(language),
version_check_(true), incognito_mode_(incognito),
is_widget_mode_(widget_mode),
- route_all_top_level_navigations_(route_all_top_level_navigations) {
+ route_all_top_level_navigations_(route_all_top_level_navigations),
+ send_shutdown_delay_switch_(send_shutdown_delay_switch) {
}
~ChromeFrameLaunchParams() {
@@ -184,6 +186,10 @@ class ChromeFrameLaunchParams : // NOLINT
return route_all_top_level_navigations_;
}
+ bool send_shutdown_delay_switch() const {
+ return send_shutdown_delay_switch_;
+ }
+
protected:
int launch_timeout_;
GURL url_;
@@ -195,6 +201,7 @@ class ChromeFrameLaunchParams : // NOLINT
bool incognito_mode_;
bool is_widget_mode_;
bool route_all_top_level_navigations_;
+ bool send_shutdown_delay_switch_;
private:
DISALLOW_COPY_AND_ASSIGN(ChromeFrameLaunchParams);
@@ -366,10 +373,15 @@ class ChromeFrameAutomationClient
void set_use_chrome_network(bool use_chrome_network) {
use_chrome_network_ = use_chrome_network;
}
+
bool use_chrome_network() const {
return use_chrome_network_;
}
+ bool send_shutdown_delay_switch() const {
+ return send_shutdown_delay_switch_;
+ }
+
#ifdef UNIT_TEST
void set_proxy_factory(ProxyFactory* factory) {
proxy_factory_ = factory;
@@ -399,11 +411,6 @@ class ChromeFrameAutomationClient
// the website to put up a confirmation dialog on unload.
void OnUnload(bool* should_unload);
- void set_route_all_top_level_navigations(
- bool route_all_top_level_navigations) {
- route_all_top_level_navigations_ = route_all_top_level_navigations;
- }
-
protected:
// ChromeFrameAutomationProxy::LaunchDelegate implementation.
virtual void LaunchComplete(ChromeFrameAutomationProxy* proxy,
@@ -432,6 +439,8 @@ class ChromeFrameAutomationClient
}
private:
+ void InitializeFieldTrials();
+
void OnMessageReceivedUIThread(const IPC::Message& msg);
void OnChannelErrorUIThread();
@@ -515,6 +524,10 @@ class ChromeFrameAutomationClient
// page without chrome frame. Defaults to false.
bool route_all_top_level_navigations_;
+ // Set to true if Chrome Frame should tell Chrome to delay shutdown after
+ // we break a connection. Currently used only as part of a field trial.
+ bool send_shutdown_delay_switch_;
+
friend class BeginNavigateContext;
friend class CreateExternalTabContext;
};
diff --git a/chrome_frame/chrome_frame_plugin.h b/chrome_frame/chrome_frame_plugin.h
index a6066f9..e71cb2f 100644
--- a/chrome_frame/chrome_frame_plugin.h
+++ b/chrome_frame/chrome_frame_plugin.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -82,7 +82,8 @@ END_MSG_MAP()
FilePath actual_profile_name = profile_path.BaseName();
launch_params_ = new ChromeFrameLaunchParams(url, referrer, profile_path,
actual_profile_name.value(), SimpleResourceLoader::GetLanguage(),
- incognito_mode, is_widget_mode, route_all_top_level_navigations);
+ incognito_mode, is_widget_mode, route_all_top_level_navigations,
+ automation_client_->send_shutdown_delay_switch());
return automation_client_->Initialize(this, launch_params_);
}
diff --git a/chrome_frame/chrome_launcher.cc b/chrome_frame/chrome_launcher.cc
index e943c7f..f1a9733 100644
--- a/chrome_frame/chrome_launcher.cc
+++ b/chrome_frame/chrome_launcher.cc
@@ -20,6 +20,7 @@ namespace {
const wchar_t* kAllowedSwitches[] = {
L"automation-channel",
L"chrome-frame",
+ L"chrome-frame-shutdown-delay",
L"chrome-version",
L"disable-background-mode",
L"disable-popup-blocking",
diff --git a/chrome_frame/chrome_tab.cc b/chrome_frame/chrome_tab.cc
index 69e72f6..8634956 100644
--- a/chrome_frame/chrome_tab.cc
+++ b/chrome_frame/chrome_tab.cc
@@ -16,6 +16,7 @@
#include "base/file_version_info.h"
#include "base/logging.h"
#include "base/logging_win.h"
+#include "base/metrics/field_trial.h"
#include "base/path_service.h"
#include "base/string16.h"
#include "base/string_number_conversions.h"
@@ -38,6 +39,7 @@
#include "chrome_frame/chrome_protocol.h"
#include "chrome_frame/dll_redirector.h"
#include "chrome_frame/exception_barrier.h"
+#include "chrome_frame/metrics_service.h"
#include "chrome_frame/resource.h"
#include "chrome_frame/utils.h"
#include "googleurl/src/url_util.h"
@@ -194,7 +196,7 @@ class ChromeTabModule : public CAtlDllModuleT<ChromeTabModule> {
ChromeTabModule _AtlModule;
base::AtExitManager* g_exit_manager = NULL;
-
+base::FieldTrialList* g_field_trial_list = NULL;
HRESULT RefreshElevationPolicy() {
const wchar_t kIEFrameDll[] = L"ieframe.dll";
@@ -858,14 +860,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance,
NULL, 0)) {
logging::LogEventProvider::Initialize(kChromeFrameProvider);
}
+
+ // Initialize the field test infrastructure. Must be done somewhere that
+ // can only get called once. For Chrome Frame, that is here.
+ g_field_trial_list = new base::FieldTrialList(
+ MetricsService::GetClientID());
} else if (reason == DLL_PROCESS_DETACH) {
+ delete g_field_trial_list;
+ g_field_trial_list = NULL;
+
DllRedirector* dll_redirector = DllRedirector::GetInstance();
DCHECK(dll_redirector);
-
dll_redirector->UnregisterAsFirstCFModule();
+
g_patch_helper.UnpatchIfNeeded();
+
delete g_exit_manager;
g_exit_manager = NULL;
+
ShutdownCrashReporting();
}
return _AtlModule.DllMain(reason, reserved);
diff --git a/chrome_frame/metrics_service.cc b/chrome_frame/metrics_service.cc
index 0186b24..eefc3ee 100644
--- a/chrome_frame/metrics_service.cc
+++ b/chrome_frame/metrics_service.cc
@@ -50,6 +50,7 @@
#include "third_party/bzip2/bzlib.h"
#endif
+#include "base/string16.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/synchronization/lock.h"
@@ -81,6 +82,8 @@ static const int kMinMilliSecondsPerUMAUpload = 600000;
base::LazyInstance<base::ThreadLocalPointer<MetricsService> >
MetricsService::g_metrics_instance_ = LAZY_INSTANCE_INITIALIZER;
+std::string MetricsService::client_id_;
+
base::Lock MetricsService::metrics_service_lock_;
// Initialize histogram statistics gathering system.
@@ -295,12 +298,7 @@ void MetricsService::SetRecording(bool enabled) {
return;
if (enabled) {
- if (client_id_.empty()) {
- client_id_ = GenerateClientID();
- // Save client id somewhere.
- }
StartRecording();
-
} else {
state_ = STOPPED;
}
@@ -308,18 +306,24 @@ void MetricsService::SetRecording(bool enabled) {
}
// static
-std::string MetricsService::GenerateClientID() {
- const int kGUIDSize = 39;
-
- GUID guid;
- HRESULT guid_result = CoCreateGuid(&guid);
- DCHECK(SUCCEEDED(guid_result));
-
- std::wstring guid_string;
- int result = StringFromGUID2(guid,
- WriteInto(&guid_string, kGUIDSize), kGUIDSize);
- DCHECK(result == kGUIDSize);
- return WideToUTF8(guid_string.substr(1, guid_string.length() - 2));
+const std::string& MetricsService::GetClientID() {
+ // TODO(robertshield): Chrome Frame shouldn't generate a new ID on every run
+ // as this apparently breaks some assumptions during metric analysis.
+ // See http://crbug.com/117188
+ if (client_id_.empty()) {
+ const int kGUIDSize = 39;
+
+ GUID guid;
+ HRESULT guid_result = CoCreateGuid(&guid);
+ DCHECK(SUCCEEDED(guid_result));
+
+ string16 guid_string;
+ int result = StringFromGUID2(guid,
+ WriteInto(&guid_string, kGUIDSize), kGUIDSize);
+ DCHECK(result == kGUIDSize);
+ client_id_ = WideToUTF8(guid_string.substr(1, guid_string.length() - 2));
+ }
+ return client_id_;
}
// static
@@ -368,7 +372,8 @@ void MetricsService::StartRecording() {
MetricsLogManager::LogType log_type = (state_ == INITIALIZED) ?
MetricsLogManager::INITIAL_LOG : MetricsLogManager::ONGOING_LOG;
- log_manager_.BeginLoggingWithLog(new MetricsLogBase(client_id_, session_id_,
+ log_manager_.BeginLoggingWithLog(new MetricsLogBase(GetClientID(),
+ session_id_,
GetVersionString()),
log_type);
if (state_ == INITIALIZED)
diff --git a/chrome_frame/metrics_service.h b/chrome_frame/metrics_service.h
index bcf4026..dbd6afc 100644
--- a/chrome_frame/metrics_service.h
+++ b/chrome_frame/metrics_service.h
@@ -14,6 +14,7 @@
#include "base/basictypes.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/synchronization/lock.h"
#include "base/threading/platform_thread.h"
@@ -35,6 +36,9 @@ class MetricsService : public MetricsServiceBase {
// Set up client ID, session ID, etc.
void InitializeMetricsState();
+ // Retrieves a client ID to use to identify self to metrics server.
+ static const std::string& GetClientID();
+
private:
MetricsService();
virtual ~MetricsService();
@@ -70,9 +74,6 @@ class MetricsService : public MetricsServiceBase {
// starting the timer is permitted).
void HandleIdleSinceLastTransmission(bool in_idle);
- // Generates a new client ID to use to identify self to metrics server.
- static std::string GenerateClientID();
-
// ChromeFrame UMA data is uploaded when this timer proc gets invoked.
static void CALLBACK TransmissionTimerProc(HWND window, unsigned int message,
unsigned int event_id,
@@ -128,7 +129,7 @@ class MetricsService : public MetricsServiceBase {
std::wstring server_url_;
// The identifier that's sent to the server with the log reports.
- std::string client_id_;
+ static std::string client_id_;
// A number that identifies the how many times the app has been launched.
int session_id_;
diff --git a/chrome_frame/test/automation_client_mock.cc b/chrome_frame/test/automation_client_mock.cc
index 3b362c6..e24d05b 100644
--- a/chrome_frame/test/automation_client_mock.cc
+++ b/chrome_frame/test/automation_client_mock.cc
@@ -137,7 +137,7 @@ void CFACWithChrome::SetUp() {
GURL empty;
launch_params_ = new ChromeFrameLaunchParams(
empty, empty, profile_path_, profile_path_.BaseName().value(), L"",
- false, false, false);
+ false, false, false, false);
launch_params_->set_version_check(false);
launch_params_->set_launch_timeout(kSaneAutomationTimeoutMs);
}
@@ -266,7 +266,7 @@ TEST_F(CFACMockTest, MockedCreateTabOk) {
GURL empty;
scoped_refptr<ChromeFrameLaunchParams> clp(new ChromeFrameLaunchParams(
empty, empty, profile_path_, profile_path_.BaseName().value(), L"",
- false, false, false));
+ false, false, false, false));
clp->set_launch_timeout(timeout);
clp->set_version_check(false);
EXPECT_TRUE(client_->Initialize(&cfd_, clp));
@@ -299,7 +299,7 @@ TEST_F(CFACMockTest, MockedCreateTabFailed) {
GURL empty;
scoped_refptr<ChromeFrameLaunchParams> clp(new ChromeFrameLaunchParams(
empty, empty, profile_path_, profile_path_.BaseName().value(), L"",
- false, false, false));
+ false, false, false, false));
clp->set_launch_timeout(timeout_);
clp->set_version_check(false);
EXPECT_TRUE(client_->Initialize(&cfd_, clp));
@@ -340,7 +340,7 @@ TEST_F(CFACMockTest, OnChannelError) {
GURL empty;
scoped_refptr<ChromeFrameLaunchParams> clp(new ChromeFrameLaunchParams(
empty, empty, profile_path_, profile_path_.BaseName().value(), L"",
- false, false, false));
+ false, false, false, false));
clp->set_launch_timeout(1); // Unneeded timeout, but can't be 0.
clp->set_version_check(false);
@@ -460,7 +460,7 @@ TEST_F(CFACMockTest, NavigateTwiceAfterInitToSameUrl) {
scoped_refptr<ChromeFrameLaunchParams> launch_params(
new ChromeFrameLaunchParams(
GURL("http://www.nonexistent.com"), empty, profile_path_,
- profile_path_.BaseName().value(), L"", false, false, false));
+ profile_path_.BaseName().value(), L"", false, false, false, false));
launch_params->set_launch_timeout(timeout);
launch_params->set_version_check(false);
EXPECT_TRUE(client_->Initialize(&cfd_, launch_params));
diff --git a/chrome_frame/test/chrome_frame_automation_mock.h b/chrome_frame/test/chrome_frame_automation_mock.h
index 3daae53..deb625c 100644
--- a/chrome_frame/test/chrome_frame_automation_mock.h
+++ b/chrome_frame/test/chrome_frame_automation_mock.h
@@ -49,7 +49,7 @@ class AutomationMockDelegate
GURL empty;
scoped_refptr<ChromeFrameLaunchParams> clp(
new ChromeFrameLaunchParams(empty, empty, profile_path, profile_name,
- language, incognito, is_widget_mode, false));
+ language, incognito, is_widget_mode, false, false));
clp->set_launch_timeout(launch_timeout);
clp->set_version_check(perform_version_check);
automation_client_->Initialize(this, clp);
diff --git a/chrome_frame/test/proxy_factory_mock.cc b/chrome_frame/test/proxy_factory_mock.cc
index 1d0defd..4932b01 100644
--- a/chrome_frame/test/proxy_factory_mock.cc
+++ b/chrome_frame/test/proxy_factory_mock.cc
@@ -38,7 +38,7 @@ ChromeFrameLaunchParams* ProxyFactoryTest::MakeLaunchParams(
ChromeFrameLaunchParams* params =
new ChromeFrameLaunchParams(empty, empty, profile_path,
profile_path.BaseName().value(), L"", false,
- false, false);
+ false, false, false);
params->set_launch_timeout(0);
params->set_version_check(false);
return params;
diff --git a/chrome_frame/test/run_all_unittests.cc b/chrome_frame/test/run_all_unittests.cc
index defc880..7e23640 100644
--- a/chrome_frame/test/run_all_unittests.cc
+++ b/chrome_frame/test/run_all_unittests.cc
@@ -5,6 +5,7 @@
#include <atlbase.h>
#include "base/command_line.h"
+#include "base/metrics/field_trial.h"
#include "base/process_util.h"
#include "base/test/test_suite.h"
#include "base/threading/platform_thread.h"
@@ -48,6 +49,10 @@ int main(int argc, char **argv) {
_set_purecall_handler(PureCall);
+ // Set up a FieldTrialList to keep any field trials we have going in
+ // Chrome Frame happy.
+ base::FieldTrialList field_trial_list("42");
+
base::TestSuite test_suite(argc, argv);
SetConfigBool(kChromeFrameHeadlessMode, true);