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
CFTestsDisabled()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
TestAutomationProvider(Profile * profile,TestAutomationProviderDelegate * delegate)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
~TestAutomationProvider()48 TestAutomationProvider::~TestAutomationProvider() {
49 delegate_->OnProviderDestroyed();
50 g_provider_instance_ = NULL;
51 }
52
OnMessageReceived(const IPC::Message & msg)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.
Send(IPC::Message * msg)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
Factory(net::URLRequest * request,net::NetworkDelegate * network_delegate,const std::string & scheme)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
GetProtocolVersion()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
NewAutomationProvider(Profile * p,const std::string & channel,TestAutomationProviderDelegate * delegate)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