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 3 // found in the LICENSE file. 4 5 #include "chrome_frame/test/net/test_automation_provider.h" 6 7 #include "base/command_line.h" 8 #include "base/file_version_info.h" 9 #include "base/path_service.h" 10 #include "chrome/common/automation_messages.h" 11 #include "chrome_frame/test/net/test_automation_resource_message_filter.h" 12 #include "net/url_request/url_request_context.h" 13 14 namespace { 15 16 // A special command line switch to just run the unit tests without CF in 17 // the picture. Can be useful when the harness itself needs to be debugged. 18 const char kNoCfTestRun[] = "no-cf-test-run"; 19 20 bool CFTestsDisabled() { 21 static bool switch_present = CommandLine::ForCurrentProcess()-> 22 HasSwitch(kNoCfTestRun); 23 return switch_present; 24 } 25 26 } // end namespace 27 28 TestAutomationProvider* TestAutomationProvider::g_provider_instance_ = NULL; 29 30 TestAutomationProvider::TestAutomationProvider( 31 Profile* profile, 32 TestAutomationProviderDelegate* delegate) 33 : AutomationProvider(profile), tab_handle_(-1), delegate_(delegate) { 34 // We need to register the protocol factory before the 35 // AutomationResourceMessageFilter registers the automation job factory to 36 // ensure that we don't inadvarently end up handling http requests which 37 // we don't expect. The initial chrome frame page for the network tests 38 // issues http requests which our test factory should not handle. 39 net::URLRequest::Deprecated::RegisterProtocolFactory( 40 "http", TestAutomationProvider::Factory); 41 net::URLRequest::Deprecated::RegisterProtocolFactory( 42 "https", TestAutomationProvider::Factory); 43 automation_resource_message_filter_ = 44 new TestAutomationResourceMessageFilter(this); 45 g_provider_instance_ = this; 46 } 47 48 TestAutomationProvider::~TestAutomationProvider() { 49 delegate_->OnProviderDestroyed(); 50 g_provider_instance_ = NULL; 51 } 52 53 bool TestAutomationProvider::OnMessageReceived(const IPC::Message& msg) { 54 if (automation_resource_message_filter_->OnMessageReceived(msg)) 55 return true; // Message handled by the filter. 56 57 return __super::OnMessageReceived(msg); 58 } 59 60 // IPC override to grab the tab handle. 61 bool TestAutomationProvider::Send(IPC::Message* msg) { 62 if (msg->type() == AutomationMsg_TabLoaded::ID) { 63 DCHECK(tab_handle_ == -1) << "Currently only support one tab"; 64 tab_handle_ = msg->routing_id(); 65 DVLOG(1) << "Got tab handle: " << tab_handle_; 66 DCHECK(tab_handle_ != -1 && tab_handle_ != 0); 67 delegate_->OnInitialTabLoaded(); 68 } 69 70 return AutomationProvider::Send(msg); 71 } 72 73 net::URLRequestJob* TestAutomationProvider::Factory( 74 net::URLRequest* request, 75 net::NetworkDelegate* network_delegate, 76 const std::string& scheme) { 77 if (CFTestsDisabled()) 78 return NULL; 79 80 if (request->url().SchemeIsHTTPOrHTTPS()) { 81 // Only look at requests that don't have any user data. 82 // ResourceDispatcherHost uses the user data for requests that it manages. 83 // We don't want to mess with those. 84 85 // We could also check if the current thread is our TestUrlRequest thread 86 // and only intercept requests that belong to that thread. 87 if (g_provider_instance_ && request->GetUserData(NULL) == NULL && 88 g_provider_instance_->tab_handle_ != -1) { 89 // We generate our own request id which is also what 90 // ResourceDispatcherHost does (well, the id is actually generated by 91 // ResourceDispatcher). Since these requests are divided into with 92 // and without userdata, we're OK. However, just to make debugging 93 // a little easier, we have a significantly higher start value. 94 static int new_id = 0x00100000; 95 URLRequestAutomationJob* job = new URLRequestAutomationJob( 96 request, network_delegate, 97 request->context()->http_user_agent_settings(), 98 g_provider_instance_->tab_handle_, new_id++, 99 g_provider_instance_->automation_resource_message_filter_, false); 100 return job; 101 } 102 } 103 104 return NULL; 105 } 106 107 std::string TestAutomationProvider::GetProtocolVersion() { 108 // Return the version of npchrome_frame.dll. We used to use 109 // chrome.dll, but the other end of the pipe in this case is 110 // actually npchrome_frame.dll (which fetches its version info from 111 // itself), and occasionally we run into RC dependency problems in 112 // incremental builds so that the version information does not get 113 // updated in one module but does in another, so better to use the 114 // exact same version to avoid hard-to-debug problems in development 115 // builds. 116 base::FilePath path; 117 PathService::Get(base::DIR_MODULE, &path); 118 path = path.AppendASCII("npchrome_frame.dll"); 119 120 std::string version; 121 scoped_ptr<FileVersionInfo> version_info( 122 FileVersionInfo::CreateFileVersionInfo(path)); 123 if (version_info.get()) { 124 version = WideToASCII(version_info->product_version()); 125 } 126 return version; 127 } 128 129 // static 130 TestAutomationProvider* TestAutomationProvider::NewAutomationProvider( 131 Profile* p, const std::string& channel, 132 TestAutomationProviderDelegate* delegate) { 133 TestAutomationProvider* automation = new TestAutomationProvider(p, delegate); 134 automation->InitializeChannel(channel); 135 automation->SetExpectedTabCount(1); 136 return automation; 137 } 138