Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: chrome/browser/extensions/activity_log/ad_injection_browsertest.cc

Issue 270623005: Update ActivityLog detection to use previous values, hrefs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "base/files/file_path.h" 5 #include "base/files/file_path.h"
6 #include "base/scoped_observer.h" 6 #include "base/scoped_observer.h"
7 #include "base/strings/string_number_conversions.h" 7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
8 #include "base/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/extensions/activity_log/activity_actions.h" 10 #include "chrome/browser/extensions/activity_log/activity_actions.h"
10 #include "chrome/browser/extensions/activity_log/activity_log.h" 11 #include "chrome/browser/extensions/activity_log/activity_log.h"
11 #include "chrome/browser/extensions/activity_log/ad_network_database.h" 12 #include "chrome/browser/extensions/activity_log/ad_network_database.h"
12 #include "chrome/browser/extensions/extension_browsertest.h" 13 #include "chrome/browser/extensions/extension_browsertest.h"
13 #include "chrome/browser/extensions/extension_test_message_listener.h" 14 #include "chrome/browser/extensions/extension_test_message_listener.h"
14 #include "chrome/test/base/ui_test_utils.h" 15 #include "chrome/test/base/ui_test_utils.h"
15 #include "extensions/common/extension.h" 16 #include "extensions/common/extension.h"
16 #include "net/test/embedded_test_server/embedded_test_server.h" 17 #include "net/test/embedded_test_server/embedded_test_server.h"
17 #include "net/test/embedded_test_server/http_response.h" 18 #include "net/test/embedded_test_server/http_response.h"
18 #include "url/gurl.h" 19 #include "url/gurl.h"
19 20
20 namespace net { 21 namespace net {
21 namespace test_server { 22 namespace test_server {
22 struct HttpRequest; 23 struct HttpRequest;
23 } 24 }
24 } 25 }
25 26
26 namespace extensions { 27 namespace extensions {
27 28
28 namespace { 29 namespace {
29 30
30 // The "ad network" that we are using. Any src or href equal to this should be 31 // The "ad network" that we are using. Any src or href equal to this should be
31 // considered an ad network. 32 // considered an ad network.
32 const char kAdNetwork[] = "http://www.known-ads.adnetwork"; 33 const char kAdNetwork1[] = "http://www.known-ads.adnetwork";
34 const char kAdNetwork2[] = "http://www.also-known-ads.adnetwork";
33 35
34 // The current stage of the test. 36 // The current stage of the test.
35 enum Stage { 37 enum Stage {
36 BEFORE_RESET, // We are about to reset the page. 38 BEFORE_RESET, // We are about to reset the page.
37 RESETTING, // We are resetting the page. 39 RESETTING, // We are resetting the page.
38 TESTING // The reset is complete, and we are testing. 40 TESTING // The reset is complete, and we are testing.
39 }; 41 };
40 42
41 // The string sent by the test to indicate that the page reset will begin. 43 // The string sent by the test to indicate that the page reset will begin.
42 const char kResetBeginString[] = "Page Reset Begin"; 44 const char kResetBeginString[] = "Page Reset Begin";
43 // The string sent by the test to indicate that page reset is complete. 45 // The string sent by the test to indicate that page reset is complete.
44 const char kResetEndString[] = "Page Reset End"; 46 const char kResetEndString[] = "Page Reset End";
45 // The string sent by the test to indicate a JS error was caught in the test. 47 // The string sent by the test to indicate a JS error was caught in the test.
46 const char kJavascriptErrorString[] = "Testing Error"; 48 const char kJavascriptErrorString[] = "Testing Error";
47 // The string sent by the test to indicate that we have concluded the full test. 49 // The string sent by the test to indicate that we have concluded the full test.
48 const char kTestCompleteString[] = "Test Complete"; 50 const char kTestCompleteString[] = "Test Complete";
49 51
52 std::string InjectionTypeToString(Action::InjectionType type) {
53 switch (type) {
54 case Action::NO_AD_INJECTION:
55 return "No Ad Injection";
56 case Action::INJECTION_NEW_AD:
57 return "Injection New Ad";
58 case Action::INJECTION_REMOVED_AD:
59 return "Injection Removed Ad";
60 case Action::INJECTION_REPLACED_AD:
61 return "Injection Replaced Ad";
62 case Action::INJECTION_LIKELY_REPLACED_AD:
63 return "Injection Likely Replaced Ad";
64 case Action::NUM_INJECTION_TYPES:
65 return "Num Injection Types";
66 }
67 return std::string();
68 }
69
50 // An implementation of ActivityLog::Observer that, for every action, sends it 70 // An implementation of ActivityLog::Observer that, for every action, sends it
51 // through Action::DidInjectAd(). This will keep track of the observed 71 // through Action::DidInjectAd(). This will keep track of the observed
52 // injections, and can be enabled or disabled as needed (for instance, this 72 // injections, and can be enabled or disabled as needed (for instance, this
53 // should be disabled while we are resetting the page). 73 // should be disabled while we are resetting the page).
54 class ActivityLogObserver : public ActivityLog::Observer { 74 class ActivityLogObserver : public ActivityLog::Observer {
55 public: 75 public:
56 explicit ActivityLogObserver(content::BrowserContext* context); 76 explicit ActivityLogObserver(content::BrowserContext* context);
57 virtual ~ActivityLogObserver(); 77 virtual ~ActivityLogObserver();
58 78
59 void set_enabled(bool enabled) { enabled_ = enabled; } 79 // Disable the observer (e.g., to reset the page).
60 size_t injection_count() const { return injection_count_; } 80 void disable() { enabled_ = false; }
81
82 // Enable the observer, resetting the state.
83 void enable() {
84 injection_type_ = Action::NO_AD_INJECTION;
85 found_multiple_injections_ = false;
86 enabled_ = true;
87 }
88
89 Action::InjectionType injection_type() const { return injection_type_; }
90
91 bool found_multiple_injections() const { return found_multiple_injections_; }
61 92
62 private: 93 private:
63 virtual void OnExtensionActivity(scoped_refptr<Action> action) OVERRIDE; 94 virtual void OnExtensionActivity(scoped_refptr<Action> action) OVERRIDE;
64 95
65 ScopedObserver<ActivityLog, ActivityLog::Observer> scoped_observer_; 96 ScopedObserver<ActivityLog, ActivityLog::Observer> scoped_observer_;
97
98 // The associated BrowserContext.
66 content::BrowserContext* context_; 99 content::BrowserContext* context_;
67 size_t injection_count_; 100
101 // The type of the last injection.
102 Action::InjectionType injection_type_;
103
104 // Whether or not we found multiple injection types (which shouldn't happen).
105 bool found_multiple_injections_;
106
107 // Whether or not the observer is enabled.
68 bool enabled_; 108 bool enabled_;
69 }; 109 };
70 110
71 ActivityLogObserver::ActivityLogObserver(content::BrowserContext* context) 111 ActivityLogObserver::ActivityLogObserver(content::BrowserContext* context)
72 : scoped_observer_(this), 112 : scoped_observer_(this),
73 context_(context), 113 context_(context),
74 injection_count_(0u), 114 injection_type_(Action::NO_AD_INJECTION),
115 found_multiple_injections_(false),
75 enabled_(false) { 116 enabled_(false) {
76 ActivityLog::GetInstance(context_)->AddObserver(this); 117 ActivityLog::GetInstance(context_)->AddObserver(this);
77 } 118 }
78 119
79 ActivityLogObserver::~ActivityLogObserver() {} 120 ActivityLogObserver::~ActivityLogObserver() {}
80 121
81 void ActivityLogObserver::OnExtensionActivity(scoped_refptr<Action> action) { 122 void ActivityLogObserver::OnExtensionActivity(scoped_refptr<Action> action) {
82 if (enabled_ && action->DidInjectAd(NULL /* no rappor service */) != 123 if (enabled_) {
felt 2014/05/08 18:43:55 nit: if (!enabled_) return;
Devlin 2014/05/08 23:13:33 Done.
83 Action::NO_AD_INJECTION) { 124 Action::InjectionType type =
84 ++injection_count_; 125 action->DidInjectAd(NULL /* no rappor service */);
126 if (type != Action::NO_AD_INJECTION) {
127 if (injection_type_ != Action::NO_AD_INJECTION)
128 found_multiple_injections_ = true;
129 injection_type_ = type;
130 }
85 } 131 }
86 } 132 }
87 133
88 // A mock for the AdNetworkDatabase. This simply says that the URL 134 // A mock for the AdNetworkDatabase. This simply says that the URL
89 // http://www.known-ads.adnetwork is an ad network, and nothing else is. 135 // http://www.known-ads.adnetwork is an ad network, and nothing else is.
90 class TestAdNetworkDatabase : public AdNetworkDatabase { 136 class TestAdNetworkDatabase : public AdNetworkDatabase {
91 public: 137 public:
92 TestAdNetworkDatabase(); 138 TestAdNetworkDatabase();
93 virtual ~TestAdNetworkDatabase(); 139 virtual ~TestAdNetworkDatabase();
94 140
95 private: 141 private:
96 virtual bool IsAdNetwork(const GURL& url) const OVERRIDE; 142 virtual bool IsAdNetwork(const GURL& url) const OVERRIDE;
97 143
98 GURL ad_network_url_; 144 GURL ad_network_url1_;
145 GURL ad_network_url2_;
99 }; 146 };
100 147
101 TestAdNetworkDatabase::TestAdNetworkDatabase() : ad_network_url_(kAdNetwork) {} 148 TestAdNetworkDatabase::TestAdNetworkDatabase() : ad_network_url1_(kAdNetwork1),
149 ad_network_url2_(kAdNetwork2) {
150 }
151
102 TestAdNetworkDatabase::~TestAdNetworkDatabase() {} 152 TestAdNetworkDatabase::~TestAdNetworkDatabase() {}
103 153
104 bool TestAdNetworkDatabase::IsAdNetwork(const GURL& url) const { 154 bool TestAdNetworkDatabase::IsAdNetwork(const GURL& url) const {
105 return url == ad_network_url_; 155 return url == ad_network_url1_ || url == ad_network_url2_;
106 } 156 }
107 157
108 scoped_ptr<net::test_server::HttpResponse> HandleRequest( 158 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
109 const net::test_server::HttpRequest& request) { 159 const net::test_server::HttpRequest& request) {
110 scoped_ptr<net::test_server::BasicHttpResponse> response( 160 scoped_ptr<net::test_server::BasicHttpResponse> response(
111 new net::test_server::BasicHttpResponse()); 161 new net::test_server::BasicHttpResponse());
112 response->set_code(net::HTTP_OK); 162 response->set_code(net::HTTP_OK);
113 return response.PassAs<net::test_server::HttpResponse>(); 163 return response.PassAs<net::test_server::HttpResponse>();
114 } 164 }
115 165
(...skipping 12 matching lines...) Expand all
128 178
129 // Handle the "Reset End" stage of the test. 179 // Handle the "Reset End" stage of the test.
130 testing::AssertionResult HandleResetEndStage(); 180 testing::AssertionResult HandleResetEndStage();
131 181
132 // Handle the "Testing" stage of the test. 182 // Handle the "Testing" stage of the test.
133 testing::AssertionResult HandleTestingStage(const std::string& message); 183 testing::AssertionResult HandleTestingStage(const std::string& message);
134 184
135 // Handle a JS error encountered in a test. 185 // Handle a JS error encountered in a test.
136 testing::AssertionResult HandleJSError(const std::string& message); 186 testing::AssertionResult HandleJSError(const std::string& message);
137 187
188 const std::string& last_test() const { return last_test_; }
felt 2014/05/08 18:43:55 where is this called? I can only find direct acces
Devlin 2014/05/08 23:13:33 Whoops! Originally I used it in the test body, bu
189
138 const base::FilePath& test_data_dir() { return test_data_dir_; } 190 const base::FilePath& test_data_dir() { return test_data_dir_; }
139 191
140 ExtensionTestMessageListener* listener() { return listener_.get(); } 192 ExtensionTestMessageListener* listener() { return listener_.get(); }
141 193
142 ActivityLogObserver* observer() { return observer_.get(); } 194 ActivityLogObserver* observer() { return observer_.get(); }
143 195
144 void set_expected_injections(size_t expected_injections) {
145 expected_injections_ = expected_injections;
146 }
147
148 private: 196 private:
149 // The name of the last completed test; used in case of unexpected failure for 197 // The name of the last completed test; used in case of unexpected failure for
150 // debugging. 198 // debugging.
151 std::string last_test_; 199 std::string last_test_;
152 200
153 // The number of expected injections.
154 size_t expected_injections_;
155
156 // A listener for any messages from our ad-injecting extension. 201 // A listener for any messages from our ad-injecting extension.
157 scoped_ptr<ExtensionTestMessageListener> listener_; 202 scoped_ptr<ExtensionTestMessageListener> listener_;
158 203
159 // An observer to be alerted when we detect ad injection. 204 // An observer to be alerted when we detect ad injection.
160 scoped_ptr<ActivityLogObserver> observer_; 205 scoped_ptr<ActivityLogObserver> observer_;
161 206
162 // The current stage of the test. 207 // The current stage of the test.
163 Stage stage_; 208 Stage stage_;
164 }; 209 };
165 210
166 AdInjectionBrowserTest::AdInjectionBrowserTest() 211 AdInjectionBrowserTest::AdInjectionBrowserTest() : stage_(BEFORE_RESET) {
167 : expected_injections_(0u), stage_(BEFORE_RESET) {} 212 }
168 213
169 AdInjectionBrowserTest::~AdInjectionBrowserTest() {} 214 AdInjectionBrowserTest::~AdInjectionBrowserTest() {
215 }
170 216
171 void AdInjectionBrowserTest::SetUpOnMainThread() { 217 void AdInjectionBrowserTest::SetUpOnMainThread() {
172 ExtensionBrowserTest::SetUpOnMainThread(); 218 ExtensionBrowserTest::SetUpOnMainThread();
173 219
174 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 220 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
175 embedded_test_server()->RegisterRequestHandler(base::Bind(&HandleRequest)); 221 embedded_test_server()->RegisterRequestHandler(base::Bind(&HandleRequest));
176 222
177 test_data_dir_ = 223 test_data_dir_ =
178 test_data_dir_.AppendASCII("activity_log").AppendASCII("ad_injection"); 224 test_data_dir_.AppendASCII("activity_log").AppendASCII("ad_injection");
179 observer_.reset(new ActivityLogObserver(profile())); 225 observer_.reset(new ActivityLogObserver(profile()));
(...skipping 21 matching lines...) Expand all
201 } 247 }
202 248
203 testing::AssertionResult AdInjectionBrowserTest::HandleResetBeginStage() { 249 testing::AssertionResult AdInjectionBrowserTest::HandleResetBeginStage() {
204 if (stage_ != BEFORE_RESET) { 250 if (stage_ != BEFORE_RESET) {
205 return testing::AssertionFailure() 251 return testing::AssertionFailure()
206 << "In incorrect stage. Last Test: " << last_test_; 252 << "In incorrect stage. Last Test: " << last_test_;
207 } 253 }
208 254
209 // Stop looking for ad injection, since some of the reset could be considered 255 // Stop looking for ad injection, since some of the reset could be considered
210 // ad injection. 256 // ad injection.
211 observer()->set_enabled(false); 257 observer()->disable();
212 stage_ = RESETTING; 258 stage_ = RESETTING;
213 return testing::AssertionSuccess(); 259 return testing::AssertionSuccess();
214 } 260 }
215 261
216 testing::AssertionResult AdInjectionBrowserTest::HandleResetEndStage() { 262 testing::AssertionResult AdInjectionBrowserTest::HandleResetEndStage() {
217 if (stage_ != RESETTING) { 263 if (stage_ != RESETTING) {
218 return testing::AssertionFailure() 264 return testing::AssertionFailure()
219 << "In incorrect stage. Last test: " << last_test_; 265 << "In incorrect stage. Last test: " << last_test_;
220 } 266 }
221 267
222 // Look for ad injection again, now that the reset is over. 268 // Look for ad injection again, now that the reset is over.
223 observer()->set_enabled(true); 269 observer()->enable();
224 stage_ = TESTING; 270 stage_ = TESTING;
225 return testing::AssertionSuccess(); 271 return testing::AssertionSuccess();
226 } 272 }
227 273
228 testing::AssertionResult AdInjectionBrowserTest::HandleTestingStage( 274 testing::AssertionResult AdInjectionBrowserTest::HandleTestingStage(
229 const std::string& message) { 275 const std::string& message) {
230 if (stage_ != TESTING) { 276 if (stage_ != TESTING) {
231 return testing::AssertionFailure() 277 return testing::AssertionFailure()
232 << "In incorrect stage. Last test: " << last_test_; 278 << "In incorrect stage. Last test: " << last_test_;
233 } 279 }
234 280
235 // The format for a testing message is: 281 // The format for a testing message is:
236 // "<test_name>:<expected_change>" 282 // "<test_name>:<expected_change>"
237 // where <test_name> is the name of the test and <expected_change> is 283 // where <test_name> is the name of the test and <expected_change> is
238 // either -1 for no ad injection (to test against false positives) or the 284 // either -1 for no ad injection (to test against false positives) or the
239 // number corresponding to ad_detection::InjectionType. 285 // number corresponding to ad_detection::InjectionType.
240 size_t sep = message.find(':'); 286 size_t sep = message.find(':');
241 int expected_change = -1; 287 int expected_change = -1;
242 if (sep == std::string::npos || 288 if (sep == std::string::npos ||
243 !base::StringToInt(message.substr(sep + 1), &expected_change) || 289 !base::StringToInt(message.substr(sep + 1), &expected_change) ||
244 (expected_change < Action::NO_AD_INJECTION || 290 (expected_change < Action::NO_AD_INJECTION ||
245 expected_change >= Action::NUM_INJECTION_TYPES)) { 291 expected_change >= Action::NUM_INJECTION_TYPES)) {
246 return testing::AssertionFailure() 292 return testing::AssertionFailure()
247 << "Invalid message received for testing stage: " << message; 293 << "Invalid message received for testing stage: " << message;
248 } 294 }
249 295
250 last_test_ = message.substr(0, sep); 296 last_test_ = message.substr(0, sep);
251 297
252 // TODO(rdevlin.cronin): Currently, we lump all kinds of ad injection into 298 Action::InjectionType expected_injection =
253 // one counter, because we can't differentiate (or catch all of them). Change 299 static_cast<Action::InjectionType>(expected_change);
254 // this when we can.
255 // Increment the expected change, and compare.
256 if (expected_change != Action::NO_AD_INJECTION)
257 ++expected_injections_;
258 std::string error; 300 std::string error;
259 if (expected_injections_ != observer()->injection_count()) { 301 if (observer()->found_multiple_injections()) {
302 error = "Found multiple injection types. "
303 "Only one injection is expected per test.";
304 } else if (expected_injection != observer()->injection_type()) {
260 // We need these static casts, because size_t is different on different 305 // We need these static casts, because size_t is different on different
261 // architectures, and printf becomes unhappy. 306 // architectures, and printf becomes unhappy.
262 error = 307 error = base::StringPrintf(
263 base::StringPrintf("Injection Count Mismatch: Expected %u, Actual %u", 308 "Incorrect Injection Found: Expected: %s, Actual: %s",
264 static_cast<unsigned int>(expected_injections_), 309 InjectionTypeToString(expected_injection).c_str(),
265 static_cast<unsigned int>( 310 InjectionTypeToString(observer()->injection_type()).c_str());
266 observer()->injection_count()));
267 } 311 }
268 312
269 stage_ = BEFORE_RESET; 313 stage_ = BEFORE_RESET;
270 314
271 if (!error.empty()) 315 if (!error.empty()) {
272 return testing::AssertionFailure() << error; 316 return testing::AssertionFailure()
317 << "Error in Test '" << last_test_ << "': " << error;
318 }
273 319
274 return testing::AssertionSuccess(); 320 return testing::AssertionSuccess();
275 } 321 }
276 322
277 testing::AssertionResult AdInjectionBrowserTest::HandleJSError( 323 testing::AssertionResult AdInjectionBrowserTest::HandleJSError(
278 const std::string& message) { 324 const std::string& message) {
279 // The format for a testing message is: 325 // The format for a testing message is:
280 // "Testing Error:<test_name>:<error>" 326 // "Testing Error:<test_name>:<error>"
281 // where <test_name> is the name of the test and <error> is the error which 327 // where <test_name> is the name of the test and <error> is the error which
282 // was encountered. 328 // was encountered.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 ASSERT_TRUE(HandleResetEndStage()); 367 ASSERT_TRUE(HandleResetEndStage());
322 } else if (!message.compare( 368 } else if (!message.compare(
323 0, strlen(kJavascriptErrorString), kJavascriptErrorString)) { 369 0, strlen(kJavascriptErrorString), kJavascriptErrorString)) {
324 EXPECT_TRUE(HandleJSError(message)); 370 EXPECT_TRUE(HandleJSError(message));
325 } else if (message == kTestCompleteString) { 371 } else if (message == kTestCompleteString) {
326 break; // We're done! 372 break; // We're done!
327 } else { // We're in some kind of test. 373 } else { // We're in some kind of test.
328 EXPECT_TRUE(HandleTestingStage(message)); 374 EXPECT_TRUE(HandleTestingStage(message));
329 } 375 }
330 376
331 // We set the expected injections to be whatever they actually are so that
332 // we only fail one test, instead of all subsequent tests.
333 set_expected_injections(observer()->injection_count());
334
335 // In all cases (except for "Test Complete", in which case we already 377 // In all cases (except for "Test Complete", in which case we already
336 // break'ed), we reply with a continue message. 378 // break'ed), we reply with a continue message.
337 listener()->Reply("Continue"); 379 listener()->Reply("Continue");
338 listener()->Reset(); 380 listener()->Reset();
339 } 381 }
340 } 382 }
341 383
342 // TODO(rdevlin.cronin): We test a good amount of ways of injecting ads with 384 // TODO(rdevlin.cronin): We test a good amount of ways of injecting ads with
343 // the above test, but more is better in testing. 385 // the above test, but more is better in testing.
344 // See crbug.com/357204. 386 // See crbug.com/357204.
345 387
346 } // namespace extensions 388 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/activity_log/activity_log.cc ('k') | chrome/browser/extensions/activity_log/uma_policy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698