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

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_NEW_AD:
63 return "Injection Likely New Ad";
64 case Action::INJECTION_LIKELY_REPLACED_AD:
65 return "Injection Likely Replaced Ad";
66 case Action::NUM_INJECTION_TYPES:
67 return "Num Injection Types";
68 }
69 return std::string();
70 }
71
50 // An implementation of ActivityLog::Observer that, for every action, sends it 72 // An implementation of ActivityLog::Observer that, for every action, sends it
51 // through Action::DidInjectAd(). This will keep track of the observed 73 // through Action::DidInjectAd(). This will keep track of the observed
52 // injections, and can be enabled or disabled as needed (for instance, this 74 // injections, and can be enabled or disabled as needed (for instance, this
53 // should be disabled while we are resetting the page). 75 // should be disabled while we are resetting the page).
54 class ActivityLogObserver : public ActivityLog::Observer { 76 class ActivityLogObserver : public ActivityLog::Observer {
55 public: 77 public:
56 explicit ActivityLogObserver(content::BrowserContext* context); 78 explicit ActivityLogObserver(content::BrowserContext* context);
57 virtual ~ActivityLogObserver(); 79 virtual ~ActivityLogObserver();
58 80
59 void set_enabled(bool enabled) { enabled_ = enabled; } 81 // Disable the observer (e.g., to reset the page).
60 size_t injection_count() const { return injection_count_; } 82 void disable() { enabled_ = false; }
83
84 // Enable the observer, resetting the state.
85 void enable() {
86 injection_type_ = Action::NO_AD_INJECTION;
87 found_multiple_injections_ = false;
88 enabled_ = true;
89 }
90
91 Action::InjectionType injection_type() const { return injection_type_; }
92
93 bool found_multiple_injections() const { return found_multiple_injections_; }
61 94
62 private: 95 private:
63 virtual void OnExtensionActivity(scoped_refptr<Action> action) OVERRIDE; 96 virtual void OnExtensionActivity(scoped_refptr<Action> action) OVERRIDE;
64 97
65 ScopedObserver<ActivityLog, ActivityLog::Observer> scoped_observer_; 98 ScopedObserver<ActivityLog, ActivityLog::Observer> scoped_observer_;
99
100 // The associated BrowserContext.
66 content::BrowserContext* context_; 101 content::BrowserContext* context_;
67 size_t injection_count_; 102
103 // The type of the last injection.
104 Action::InjectionType injection_type_;
105
106 // Whether or not we found multiple injection types (which shouldn't happen).
107 bool found_multiple_injections_;
108
109 // Whether or not the observer is enabled.
68 bool enabled_; 110 bool enabled_;
69 }; 111 };
70 112
71 ActivityLogObserver::ActivityLogObserver(content::BrowserContext* context) 113 ActivityLogObserver::ActivityLogObserver(content::BrowserContext* context)
72 : scoped_observer_(this), 114 : scoped_observer_(this),
73 context_(context), 115 context_(context),
74 injection_count_(0u), 116 injection_type_(Action::NO_AD_INJECTION),
117 found_multiple_injections_(false),
75 enabled_(false) { 118 enabled_(false) {
76 ActivityLog::GetInstance(context_)->AddObserver(this); 119 ActivityLog::GetInstance(context_)->AddObserver(this);
77 } 120 }
78 121
79 ActivityLogObserver::~ActivityLogObserver() {} 122 ActivityLogObserver::~ActivityLogObserver() {}
80 123
81 void ActivityLogObserver::OnExtensionActivity(scoped_refptr<Action> action) { 124 void ActivityLogObserver::OnExtensionActivity(scoped_refptr<Action> action) {
82 if (enabled_ && action->DidInjectAd(NULL /* no rappor service */) != 125 if (!enabled_)
83 Action::NO_AD_INJECTION) { 126 return;
84 ++injection_count_; 127
128 Action::InjectionType type =
129 action->DidInjectAd(NULL /* no rappor service */);
130 if (type != Action::NO_AD_INJECTION) {
131 if (injection_type_ != Action::NO_AD_INJECTION)
132 found_multiple_injections_ = true;
133 injection_type_ = type;
85 } 134 }
86 } 135 }
87 136
88 // A mock for the AdNetworkDatabase. This simply says that the URL 137 // 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. 138 // http://www.known-ads.adnetwork is an ad network, and nothing else is.
90 class TestAdNetworkDatabase : public AdNetworkDatabase { 139 class TestAdNetworkDatabase : public AdNetworkDatabase {
91 public: 140 public:
92 TestAdNetworkDatabase(); 141 TestAdNetworkDatabase();
93 virtual ~TestAdNetworkDatabase(); 142 virtual ~TestAdNetworkDatabase();
94 143
95 private: 144 private:
96 virtual bool IsAdNetwork(const GURL& url) const OVERRIDE; 145 virtual bool IsAdNetwork(const GURL& url) const OVERRIDE;
97 146
98 GURL ad_network_url_; 147 GURL ad_network_url1_;
148 GURL ad_network_url2_;
99 }; 149 };
100 150
101 TestAdNetworkDatabase::TestAdNetworkDatabase() : ad_network_url_(kAdNetwork) {} 151 TestAdNetworkDatabase::TestAdNetworkDatabase() : ad_network_url1_(kAdNetwork1),
152 ad_network_url2_(kAdNetwork2) {
153 }
154
102 TestAdNetworkDatabase::~TestAdNetworkDatabase() {} 155 TestAdNetworkDatabase::~TestAdNetworkDatabase() {}
103 156
104 bool TestAdNetworkDatabase::IsAdNetwork(const GURL& url) const { 157 bool TestAdNetworkDatabase::IsAdNetwork(const GURL& url) const {
105 return url == ad_network_url_; 158 return url == ad_network_url1_ || url == ad_network_url2_;
106 } 159 }
107 160
108 scoped_ptr<net::test_server::HttpResponse> HandleRequest( 161 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
109 const net::test_server::HttpRequest& request) { 162 const net::test_server::HttpRequest& request) {
110 scoped_ptr<net::test_server::BasicHttpResponse> response( 163 scoped_ptr<net::test_server::BasicHttpResponse> response(
111 new net::test_server::BasicHttpResponse()); 164 new net::test_server::BasicHttpResponse());
112 response->set_code(net::HTTP_OK); 165 response->set_code(net::HTTP_OK);
113 return response.PassAs<net::test_server::HttpResponse>(); 166 return response.PassAs<net::test_server::HttpResponse>();
114 } 167 }
115 168
(...skipping 18 matching lines...) Expand all
134 187
135 // Handle a JS error encountered in a test. 188 // Handle a JS error encountered in a test.
136 testing::AssertionResult HandleJSError(const std::string& message); 189 testing::AssertionResult HandleJSError(const std::string& message);
137 190
138 const base::FilePath& test_data_dir() { return test_data_dir_; } 191 const base::FilePath& test_data_dir() { return test_data_dir_; }
139 192
140 ExtensionTestMessageListener* listener() { return listener_.get(); } 193 ExtensionTestMessageListener* listener() { return listener_.get(); }
141 194
142 ActivityLogObserver* observer() { return observer_.get(); } 195 ActivityLogObserver* observer() { return observer_.get(); }
143 196
144 void set_expected_injections(size_t expected_injections) {
145 expected_injections_ = expected_injections;
146 }
147
148 private: 197 private:
149 // The name of the last completed test; used in case of unexpected failure for 198 // The name of the last completed test; used in case of unexpected failure for
150 // debugging. 199 // debugging.
151 std::string last_test_; 200 std::string last_test_;
152 201
153 // The number of expected injections.
154 size_t expected_injections_;
155
156 // A listener for any messages from our ad-injecting extension. 202 // A listener for any messages from our ad-injecting extension.
157 scoped_ptr<ExtensionTestMessageListener> listener_; 203 scoped_ptr<ExtensionTestMessageListener> listener_;
158 204
159 // An observer to be alerted when we detect ad injection. 205 // An observer to be alerted when we detect ad injection.
160 scoped_ptr<ActivityLogObserver> observer_; 206 scoped_ptr<ActivityLogObserver> observer_;
161 207
162 // The current stage of the test. 208 // The current stage of the test.
163 Stage stage_; 209 Stage stage_;
164 }; 210 };
165 211
166 AdInjectionBrowserTest::AdInjectionBrowserTest() 212 AdInjectionBrowserTest::AdInjectionBrowserTest() : stage_(BEFORE_RESET) {
167 : expected_injections_(0u), stage_(BEFORE_RESET) {} 213 }
168 214
169 AdInjectionBrowserTest::~AdInjectionBrowserTest() {} 215 AdInjectionBrowserTest::~AdInjectionBrowserTest() {
216 }
170 217
171 void AdInjectionBrowserTest::SetUpOnMainThread() { 218 void AdInjectionBrowserTest::SetUpOnMainThread() {
172 ExtensionBrowserTest::SetUpOnMainThread(); 219 ExtensionBrowserTest::SetUpOnMainThread();
173 220
174 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 221 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
175 embedded_test_server()->RegisterRequestHandler(base::Bind(&HandleRequest)); 222 embedded_test_server()->RegisterRequestHandler(base::Bind(&HandleRequest));
176 223
177 test_data_dir_ = 224 test_data_dir_ =
178 test_data_dir_.AppendASCII("activity_log").AppendASCII("ad_injection"); 225 test_data_dir_.AppendASCII("activity_log").AppendASCII("ad_injection");
179 observer_.reset(new ActivityLogObserver(profile())); 226 observer_.reset(new ActivityLogObserver(profile()));
(...skipping 21 matching lines...) Expand all
201 } 248 }
202 249
203 testing::AssertionResult AdInjectionBrowserTest::HandleResetBeginStage() { 250 testing::AssertionResult AdInjectionBrowserTest::HandleResetBeginStage() {
204 if (stage_ != BEFORE_RESET) { 251 if (stage_ != BEFORE_RESET) {
205 return testing::AssertionFailure() 252 return testing::AssertionFailure()
206 << "In incorrect stage. Last Test: " << last_test_; 253 << "In incorrect stage. Last Test: " << last_test_;
207 } 254 }
208 255
209 // Stop looking for ad injection, since some of the reset could be considered 256 // Stop looking for ad injection, since some of the reset could be considered
210 // ad injection. 257 // ad injection.
211 observer()->set_enabled(false); 258 observer()->disable();
212 stage_ = RESETTING; 259 stage_ = RESETTING;
213 return testing::AssertionSuccess(); 260 return testing::AssertionSuccess();
214 } 261 }
215 262
216 testing::AssertionResult AdInjectionBrowserTest::HandleResetEndStage() { 263 testing::AssertionResult AdInjectionBrowserTest::HandleResetEndStage() {
217 if (stage_ != RESETTING) { 264 if (stage_ != RESETTING) {
218 return testing::AssertionFailure() 265 return testing::AssertionFailure()
219 << "In incorrect stage. Last test: " << last_test_; 266 << "In incorrect stage. Last test: " << last_test_;
220 } 267 }
221 268
222 // Look for ad injection again, now that the reset is over. 269 // Look for ad injection again, now that the reset is over.
223 observer()->set_enabled(true); 270 observer()->enable();
224 stage_ = TESTING; 271 stage_ = TESTING;
225 return testing::AssertionSuccess(); 272 return testing::AssertionSuccess();
226 } 273 }
227 274
228 testing::AssertionResult AdInjectionBrowserTest::HandleTestingStage( 275 testing::AssertionResult AdInjectionBrowserTest::HandleTestingStage(
229 const std::string& message) { 276 const std::string& message) {
230 if (stage_ != TESTING) { 277 if (stage_ != TESTING) {
231 return testing::AssertionFailure() 278 return testing::AssertionFailure()
232 << "In incorrect stage. Last test: " << last_test_; 279 << "In incorrect stage. Last test: " << last_test_;
233 } 280 }
234 281
235 // The format for a testing message is: 282 // The format for a testing message is:
236 // "<test_name>:<expected_change>" 283 // "<test_name>:<expected_change>"
237 // where <test_name> is the name of the test and <expected_change> is 284 // 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 285 // either -1 for no ad injection (to test against false positives) or the
239 // number corresponding to ad_detection::InjectionType. 286 // number corresponding to ad_detection::InjectionType.
240 size_t sep = message.find(':'); 287 size_t sep = message.find(':');
241 int expected_change = -1; 288 int expected_change = -1;
242 if (sep == std::string::npos || 289 if (sep == std::string::npos ||
243 !base::StringToInt(message.substr(sep + 1), &expected_change) || 290 !base::StringToInt(message.substr(sep + 1), &expected_change) ||
244 (expected_change < Action::NO_AD_INJECTION || 291 (expected_change < Action::NO_AD_INJECTION ||
245 expected_change >= Action::NUM_INJECTION_TYPES)) { 292 expected_change >= Action::NUM_INJECTION_TYPES)) {
246 return testing::AssertionFailure() 293 return testing::AssertionFailure()
247 << "Invalid message received for testing stage: " << message; 294 << "Invalid message received for testing stage: " << message;
248 } 295 }
249 296
250 last_test_ = message.substr(0, sep); 297 last_test_ = message.substr(0, sep);
251 298
252 // TODO(rdevlin.cronin): Currently, we lump all kinds of ad injection into 299 Action::InjectionType expected_injection =
253 // one counter, because we can't differentiate (or catch all of them). Change 300 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; 301 std::string error;
259 if (expected_injections_ != observer()->injection_count()) { 302 if (observer()->found_multiple_injections()) {
303 error = "Found multiple injection types. "
304 "Only one injection is expected per test.";
305 } else if (expected_injection != observer()->injection_type()) {
260 // We need these static casts, because size_t is different on different 306 // We need these static casts, because size_t is different on different
261 // architectures, and printf becomes unhappy. 307 // architectures, and printf becomes unhappy.
262 error = 308 error = base::StringPrintf(
263 base::StringPrintf("Injection Count Mismatch: Expected %u, Actual %u", 309 "Incorrect Injection Found: Expected: %s, Actual: %s",
264 static_cast<unsigned int>(expected_injections_), 310 InjectionTypeToString(expected_injection).c_str(),
265 static_cast<unsigned int>( 311 InjectionTypeToString(observer()->injection_type()).c_str());
266 observer()->injection_count()));
267 } 312 }
268 313
269 stage_ = BEFORE_RESET; 314 stage_ = BEFORE_RESET;
270 315
271 if (!error.empty()) 316 if (!error.empty()) {
272 return testing::AssertionFailure() << error; 317 return testing::AssertionFailure()
318 << "Error in Test '" << last_test_ << "': " << error;
319 }
273 320
274 return testing::AssertionSuccess(); 321 return testing::AssertionSuccess();
275 } 322 }
276 323
277 testing::AssertionResult AdInjectionBrowserTest::HandleJSError( 324 testing::AssertionResult AdInjectionBrowserTest::HandleJSError(
278 const std::string& message) { 325 const std::string& message) {
279 // The format for a testing message is: 326 // The format for a testing message is:
280 // "Testing Error:<test_name>:<error>" 327 // "Testing Error:<test_name>:<error>"
281 // where <test_name> is the name of the test and <error> is the error which 328 // where <test_name> is the name of the test and <error> is the error which
282 // was encountered. 329 // was encountered.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 ASSERT_TRUE(HandleResetEndStage()); 368 ASSERT_TRUE(HandleResetEndStage());
322 } else if (!message.compare( 369 } else if (!message.compare(
323 0, strlen(kJavascriptErrorString), kJavascriptErrorString)) { 370 0, strlen(kJavascriptErrorString), kJavascriptErrorString)) {
324 EXPECT_TRUE(HandleJSError(message)); 371 EXPECT_TRUE(HandleJSError(message));
325 } else if (message == kTestCompleteString) { 372 } else if (message == kTestCompleteString) {
326 break; // We're done! 373 break; // We're done!
327 } else { // We're in some kind of test. 374 } else { // We're in some kind of test.
328 EXPECT_TRUE(HandleTestingStage(message)); 375 EXPECT_TRUE(HandleTestingStage(message));
329 } 376 }
330 377
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 378 // In all cases (except for "Test Complete", in which case we already
336 // break'ed), we reply with a continue message. 379 // break'ed), we reply with a continue message.
337 listener()->Reply("Continue"); 380 listener()->Reply("Continue");
338 listener()->Reset(); 381 listener()->Reset();
339 } 382 }
340 } 383 }
341 384
342 // TODO(rdevlin.cronin): We test a good amount of ways of injecting ads with 385 // TODO(rdevlin.cronin): We test a good amount of ways of injecting ads with
343 // the above test, but more is better in testing. 386 // the above test, but more is better in testing.
344 // See crbug.com/357204. 387 // See crbug.com/357204.
345 388
346 } // namespace extensions 389 } // 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