| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome_frame/chrome_frame_automation.h" | 5 #include "chrome_frame/chrome_frame_automation.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
| 13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 14 #include "base/file_version_info.h" | 14 #include "base/file_version_info.h" |
| 15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/metrics/field_trial.h" | |
| 18 #include "base/path_service.h" | 17 #include "base/path_service.h" |
| 19 #include "base/process_util.h" | 18 #include "base/process_util.h" |
| 20 #include "base/string_util.h" | 19 #include "base/string_util.h" |
| 21 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
| 22 #include "base/synchronization/waitable_event.h" | 21 #include "base/synchronization/waitable_event.h" |
| 23 #include "base/sys_info.h" | 22 #include "base/sys_info.h" |
| 24 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
| 25 #include "chrome/app/client_util.h" | 24 #include "chrome/app/client_util.h" |
| 26 #include "chrome/common/automation_messages.h" | 25 #include "chrome/common/automation_messages.h" |
| 27 #include "chrome/common/chrome_constants.h" | 26 #include "chrome/common/chrome_constants.h" |
| 28 #include "chrome/common/chrome_switches.h" | 27 #include "chrome/common/chrome_switches.h" |
| 29 #include "chrome/test/automation/tab_proxy.h" | 28 #include "chrome/test/automation/tab_proxy.h" |
| 30 #include "chrome_frame/chrome_launcher_utils.h" | 29 #include "chrome_frame/chrome_launcher_utils.h" |
| 31 #include "chrome_frame/crash_reporting/crash_metrics.h" | 30 #include "chrome_frame/crash_reporting/crash_metrics.h" |
| 32 #include "chrome_frame/custom_sync_call_context.h" | 31 #include "chrome_frame/custom_sync_call_context.h" |
| 33 #include "chrome_frame/navigation_constraints.h" | 32 #include "chrome_frame/navigation_constraints.h" |
| 34 #include "chrome_frame/simple_resource_loader.h" | 33 #include "chrome_frame/simple_resource_loader.h" |
| 35 #include "chrome_frame/utils.h" | 34 #include "chrome_frame/utils.h" |
| 36 #include "ui/base/ui_base_switches.h" | 35 #include "ui/base/ui_base_switches.h" |
| 37 | 36 |
| 38 namespace { | 37 namespace { |
| 39 | 38 |
| 40 #ifdef NDEBUG | 39 #ifdef NDEBUG |
| 41 int64 kAutomationServerReasonableLaunchDelay = 1000; // in milliseconds | 40 int64 kAutomationServerReasonableLaunchDelay = 1000; // in milliseconds |
| 42 #else | 41 #else |
| 43 int64 kAutomationServerReasonableLaunchDelay = 1000 * 10; | 42 int64 kAutomationServerReasonableLaunchDelay = 1000 * 10; |
| 44 #endif | 43 #endif |
| 45 | 44 |
| 46 const char kChromeShutdownDelaySeconds[] = "30"; | |
| 47 const char kWithDelayFieldTrialName[] = "WithShutdownDelay"; | |
| 48 const char kNoDelayFieldTrialName[] = "NoShutdownDelay"; | |
| 49 | |
| 50 } // namespace | 45 } // namespace |
| 51 | 46 |
| 52 class ChromeFrameAutomationProxyImpl::TabProxyNotificationMessageFilter | 47 class ChromeFrameAutomationProxyImpl::TabProxyNotificationMessageFilter |
| 53 : public IPC::ChannelProxy::MessageFilter { | 48 : public IPC::ChannelProxy::MessageFilter { |
| 54 public: | 49 public: |
| 55 explicit TabProxyNotificationMessageFilter(AutomationHandleTracker* tracker) | 50 explicit TabProxyNotificationMessageFilter(AutomationHandleTracker* tracker) |
| 56 : tracker_(tracker) { | 51 : tracker_(tracker) { |
| 57 } | 52 } |
| 58 | 53 |
| 59 void AddTabProxy(AutomationHandle tab_proxy) { | 54 void AddTabProxy(AutomationHandle tab_proxy) { |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 // In headless mode runs like reliability test runs we want full crash dumps | 290 // In headless mode runs like reliability test runs we want full crash dumps |
| 296 // from chrome. | 291 // from chrome. |
| 297 if (IsHeadlessMode()) | 292 if (IsHeadlessMode()) |
| 298 command_line->AppendSwitch(switches::kFullMemoryCrashReport); | 293 command_line->AppendSwitch(switches::kFullMemoryCrashReport); |
| 299 | 294 |
| 300 // In accessible mode automation tests expect renderer accessibility to be | 295 // In accessible mode automation tests expect renderer accessibility to be |
| 301 // enabled in chrome. | 296 // enabled in chrome. |
| 302 if (IsAccessibleMode()) | 297 if (IsAccessibleMode()) |
| 303 command_line->AppendSwitch(switches::kForceRendererAccessibility); | 298 command_line->AppendSwitch(switches::kForceRendererAccessibility); |
| 304 | 299 |
| 305 if (params->send_shutdown_delay_switch()) | |
| 306 command_line->AppendSwitchASCII(switches::kChromeFrameShutdownDelay, | |
| 307 kChromeShutdownDelaySeconds); | |
| 308 | |
| 309 DVLOG(1) << "Profile path: " << params->profile_path().value(); | 300 DVLOG(1) << "Profile path: " << params->profile_path().value(); |
| 310 command_line->AppendSwitchPath(switches::kUserDataDir, | 301 command_line->AppendSwitchPath(switches::kUserDataDir, |
| 311 params->profile_path()); | 302 params->profile_path()); |
| 312 | 303 |
| 313 // Ensure that Chrome is running the specified version of chrome.dll. | 304 // Ensure that Chrome is running the specified version of chrome.dll. |
| 314 command_line->AppendSwitchNative(switches::kChromeVersion, | 305 command_line->AppendSwitchNative(switches::kChromeVersion, |
| 315 GetCurrentModuleVersion()); | 306 GetCurrentModuleVersion()); |
| 316 | 307 |
| 317 if (!params->language().empty()) | 308 if (!params->language().empty()) |
| 318 command_line->AppendSwitchNative(switches::kLang, params->language()); | 309 command_line->AppendSwitchNative(switches::kLang, params->language()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 343 // version string it reported. | 334 // version string it reported. |
| 344 launch_result_ = proxy->WaitForAppLaunch(); | 335 launch_result_ = proxy->WaitForAppLaunch(); |
| 345 launch_stats.Dump(); | 336 launch_stats.Dump(); |
| 346 | 337 |
| 347 base::TimeDelta delta = | 338 base::TimeDelta delta = |
| 348 base::TimeTicks::Now() - automation_server_launch_start_time_; | 339 base::TimeTicks::Now() - automation_server_launch_start_time_; |
| 349 | 340 |
| 350 if (launch_result_ == AUTOMATION_SUCCESS) { | 341 if (launch_result_ == AUTOMATION_SUCCESS) { |
| 351 UMA_HISTOGRAM_TIMES( | 342 UMA_HISTOGRAM_TIMES( |
| 352 "ChromeFrame.AutomationServerLaunchSuccessTime", delta); | 343 "ChromeFrame.AutomationServerLaunchSuccessTime", delta); |
| 353 UMA_HISTOGRAM_TIMES( | |
| 354 base::FieldTrial::MakeName( | |
| 355 "ChromeFrame.AutomationServerLaunchSuccessTime", | |
| 356 "ChromeShutdownDelay"), | |
| 357 delta); | |
| 358 } else { | 344 } else { |
| 359 UMA_HISTOGRAM_TIMES( | 345 UMA_HISTOGRAM_TIMES( |
| 360 "ChromeFrame.AutomationServerLaunchFailedTime", delta); | 346 "ChromeFrame.AutomationServerLaunchFailedTime", delta); |
| 361 UMA_HISTOGRAM_TIMES( | |
| 362 base::FieldTrial::MakeName( | |
| 363 "ChromeFrame.AutomationServerLaunchFailedTime", | |
| 364 "ChromeShutdownDelay"), | |
| 365 delta); | |
| 366 } | 347 } |
| 367 | 348 |
| 368 UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.LaunchResult", | 349 UMA_HISTOGRAM_CUSTOM_COUNTS("ChromeFrame.LaunchResult", |
| 369 launch_result_, | 350 launch_result_, |
| 370 AUTOMATION_SUCCESS, | 351 AUTOMATION_SUCCESS, |
| 371 AUTOMATION_CREATE_TAB_FAILED, | 352 AUTOMATION_CREATE_TAB_FAILED, |
| 372 AUTOMATION_CREATE_TAB_FAILED + 1); | 353 AUTOMATION_CREATE_TAB_FAILED + 1); |
| 373 } | 354 } |
| 374 | 355 |
| 375 TRACE_EVENT_END_ETW("chromeframe.createproxy", this, ""); | 356 TRACE_EVENT_END_ETW("chromeframe.createproxy", this, ""); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 init_state_(UNINITIALIZED), | 531 init_state_(UNINITIALIZED), |
| 551 use_chrome_network_(false), | 532 use_chrome_network_(false), |
| 552 proxy_factory_(g_proxy_factory.Pointer()), | 533 proxy_factory_(g_proxy_factory.Pointer()), |
| 553 handle_top_level_requests_(false), | 534 handle_top_level_requests_(false), |
| 554 tab_handle_(-1), | 535 tab_handle_(-1), |
| 555 session_id_(-1), | 536 session_id_(-1), |
| 556 external_tab_cookie_(0), | 537 external_tab_cookie_(0), |
| 557 url_fetcher_(NULL), | 538 url_fetcher_(NULL), |
| 558 url_fetcher_flags_(PluginUrlRequestManager::NOT_THREADSAFE), | 539 url_fetcher_flags_(PluginUrlRequestManager::NOT_THREADSAFE), |
| 559 navigate_after_initialization_(false), | 540 navigate_after_initialization_(false), |
| 560 route_all_top_level_navigations_(false), | 541 route_all_top_level_navigations_(false) { |
| 561 send_shutdown_delay_switch_(true) { | |
| 562 InitializeFieldTrials(); | |
| 563 } | 542 } |
| 564 | 543 |
| 565 ChromeFrameAutomationClient::~ChromeFrameAutomationClient() { | 544 ChromeFrameAutomationClient::~ChromeFrameAutomationClient() { |
| 566 // Uninitialize must be called prior to the destructor | 545 // Uninitialize must be called prior to the destructor |
| 567 DCHECK(automation_server_ == NULL); | 546 DCHECK(automation_server_ == NULL); |
| 568 } | 547 } |
| 569 | 548 |
| 570 bool ChromeFrameAutomationClient::Initialize( | 549 bool ChromeFrameAutomationClient::Initialize( |
| 571 ChromeFrameDelegate* chrome_frame_delegate, | 550 ChromeFrameDelegate* chrome_frame_delegate, |
| 572 ChromeFrameLaunchParams* chrome_launch_params) { | 551 ChromeFrameLaunchParams* chrome_launch_params) { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 // Important: Since we will be using the referrer_ variable from a | 670 // Important: Since we will be using the referrer_ variable from a |
| 692 // different thread, we need to force a new std::string buffer instance for | 671 // different thread, we need to force a new std::string buffer instance for |
| 693 // the referrer_ GURL variable. Otherwise we can run into strangeness when | 672 // the referrer_ GURL variable. Otherwise we can run into strangeness when |
| 694 // the GURL is accessed and it could result in a bad URL that can cause the | 673 // the GURL is accessed and it could result in a bad URL that can cause the |
| 695 // referrer to be dropped or something worse. | 674 // referrer to be dropped or something worse. |
| 696 GURL referrer_gurl(referrer.c_str()); | 675 GURL referrer_gurl(referrer.c_str()); |
| 697 if (!chrome_launch_params_) { | 676 if (!chrome_launch_params_) { |
| 698 base::FilePath profile_path; | 677 base::FilePath profile_path; |
| 699 chrome_launch_params_ = new ChromeFrameLaunchParams(parsed_url, | 678 chrome_launch_params_ = new ChromeFrameLaunchParams(parsed_url, |
| 700 referrer_gurl, profile_path, L"", SimpleResourceLoader::GetLanguage(), | 679 referrer_gurl, profile_path, L"", SimpleResourceLoader::GetLanguage(), |
| 701 false, false, route_all_top_level_navigations_, | 680 false, false, route_all_top_level_navigations_); |
| 702 send_shutdown_delay_switch_); | |
| 703 } else { | 681 } else { |
| 704 chrome_launch_params_->set_referrer(referrer_gurl); | 682 chrome_launch_params_->set_referrer(referrer_gurl); |
| 705 chrome_launch_params_->set_url(parsed_url); | 683 chrome_launch_params_->set_url(parsed_url); |
| 706 } | 684 } |
| 707 | 685 |
| 708 navigate_after_initialization_ = false; | 686 navigate_after_initialization_ = false; |
| 709 | 687 |
| 710 if (is_initialized()) { | 688 if (is_initialized()) { |
| 711 BeginNavigate(); | 689 BeginNavigate(); |
| 712 } else { | 690 } else { |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 | 1008 |
| 1031 PostTask( | 1009 PostTask( |
| 1032 FROM_HERE, | 1010 FROM_HERE, |
| 1033 base::Bind( | 1011 base::Bind( |
| 1034 base::IgnoreResult( | 1012 base::IgnoreResult( |
| 1035 &ChromeFrameAutomationClient::ProcessUrlRequestMessage), | 1013 &ChromeFrameAutomationClient::ProcessUrlRequestMessage), |
| 1036 base::Unretained(this), tab, msg, true)); | 1014 base::Unretained(this), tab, msg, true)); |
| 1037 return true; | 1015 return true; |
| 1038 } | 1016 } |
| 1039 | 1017 |
| 1040 void ChromeFrameAutomationClient::InitializeFieldTrials() { | |
| 1041 static base::FieldTrial* trial = NULL; | |
| 1042 if (!trial) { | |
| 1043 // Do one-time initialization of the field trial here. | |
| 1044 // TODO(robertshield): End the field trial before March 7th 2013. | |
| 1045 scoped_refptr<base::FieldTrial> new_trial = | |
| 1046 base::FieldTrialList::FactoryGetFieldTrial( | |
| 1047 "ChromeShutdownDelay", 1000, kWithDelayFieldTrialName, | |
| 1048 2013, 3, 7, NULL); | |
| 1049 | |
| 1050 // Be consistent for this client. Note that this will only have an effect | |
| 1051 // once the client id is persisted. See http://crbug.com/117188 | |
| 1052 new_trial->UseOneTimeRandomization(); | |
| 1053 | |
| 1054 new_trial->AppendGroup(kNoDelayFieldTrialName, 500); // 50% without. | |
| 1055 | |
| 1056 trial = new_trial.get(); | |
| 1057 } | |
| 1058 | |
| 1059 // Take action depending of which group we randomly land in. | |
| 1060 if (trial->group_name() == kWithDelayFieldTrialName) | |
| 1061 send_shutdown_delay_switch_ = true; | |
| 1062 else | |
| 1063 send_shutdown_delay_switch_ = false; | |
| 1064 | |
| 1065 } | |
| 1066 | |
| 1067 // These are invoked in channel's background thread. | 1018 // These are invoked in channel's background thread. |
| 1068 // Cannot call any method of the activex here since it is a STA kind of being. | 1019 // Cannot call any method of the activex here since it is a STA kind of being. |
| 1069 // By default we marshal the IPC message to the main/GUI thread and from there | 1020 // By default we marshal the IPC message to the main/GUI thread and from there |
| 1070 // we safely invoke chrome_frame_delegate_->OnMessageReceived(msg). | 1021 // we safely invoke chrome_frame_delegate_->OnMessageReceived(msg). |
| 1071 bool ChromeFrameAutomationClient::OnMessageReceived(TabProxy* tab, | 1022 bool ChromeFrameAutomationClient::OnMessageReceived(TabProxy* tab, |
| 1072 const IPC::Message& msg) { | 1023 const IPC::Message& msg) { |
| 1073 DCHECK(tab == tab_.get()); | 1024 DCHECK(tab == tab_.get()); |
| 1074 // Quickly process network related messages. | 1025 // Quickly process network related messages. |
| 1075 if (url_fetcher_ && ProcessUrlRequestMessage(tab, msg, false)) | 1026 if (url_fetcher_ && ProcessUrlRequestMessage(tab, msg, false)) |
| 1076 return true; | 1027 return true; |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 const net::URLRequestStatus& status) { | 1287 const net::URLRequestStatus& status) { |
| 1337 automation_server_->Send(new AutomationMsg_RequestEnd( | 1288 automation_server_->Send(new AutomationMsg_RequestEnd( |
| 1338 tab_->handle(), request_id, status)); | 1289 tab_->handle(), request_id, status)); |
| 1339 } | 1290 } |
| 1340 | 1291 |
| 1341 void ChromeFrameAutomationClient::OnCookiesRetrieved(bool success, | 1292 void ChromeFrameAutomationClient::OnCookiesRetrieved(bool success, |
| 1342 const GURL& url, const std::string& cookie_string, int cookie_id) { | 1293 const GURL& url, const std::string& cookie_string, int cookie_id) { |
| 1343 automation_server_->Send(new AutomationMsg_GetCookiesHostResponse( | 1294 automation_server_->Send(new AutomationMsg_GetCookiesHostResponse( |
| 1344 tab_->handle(), success, url, cookie_string, cookie_id)); | 1295 tab_->handle(), success, url, cookie_string, cookie_id)); |
| 1345 } | 1296 } |
| OLD | NEW |