OLD | NEW |
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 // This file contains the tests for detecting extension's ad injection in | 5 // This file contains the tests for detecting extension's ad injection in |
6 // Chrome. This contains many different, independent tests, but it is all run | 6 // Chrome. This contains many different, independent tests, but it is all run |
7 // as a "single" browser test. The reason for this is that we want to do many | 7 // as a "single" browser test. The reason for this is that we want to do many |
8 // short tests for ad injection, and the set-up/tear-down time for a browsertest | 8 // short tests for ad injection, and the set-up/tear-down time for a browsertest |
9 // implementation of each would be prohibitive. | 9 // implementation of each would be prohibitive. |
10 // See also chrome/browser/extensions/activity_log/ad_injection_browsertest.cc | 10 // See also chrome/browser/extensions/activity_log/ad_injection_browsertest.cc |
(...skipping 15 matching lines...) Expand all Loading... |
26 // ---------------------------------------------------------- | 26 // ---------------------------------------------------------- |
27 | 27 |
28 // This html block is just designed to be a massive playground for ad injectors, | 28 // This html block is just designed to be a massive playground for ad injectors, |
29 // where they can let loose and have fun. | 29 // where they can let loose and have fun. |
30 // We use this to populate our page at the start of every test. | 30 // We use this to populate our page at the start of every test. |
31 var kBodyHtml = | 31 var kBodyHtml = |
32 '<iframe id="ad-iframe" src="http://www.known-ads.adnetwork"></iframe>' + | 32 '<iframe id="ad-iframe" src="http://www.known-ads.adnetwork"></iframe>' + |
33 '<iframe id="non-ad-iframe" src="http://www.not-ads.adnetwork"></iframe>' + | 33 '<iframe id="non-ad-iframe" src="http://www.not-ads.adnetwork"></iframe>' + |
34 '<embed id="ad-embed" src="http://www.known-ads.adnetwork"><embed>' + | 34 '<embed id="ad-embed" src="http://www.known-ads.adnetwork"><embed>' + |
35 '<embed id="non-ad-embed" src="http://www.not-ads.adnetwork"><embed>' + | 35 '<embed id="non-ad-embed" src="http://www.not-ads.adnetwork"><embed>' + |
36 '<a id="ad-link" href="http://www.known-ads.adnetwork"></a>' + | 36 '<a id="ad-anchor" href="http://www.known-ads.adnetwork"></a>' + |
37 '<a id="non-ad-link" href="http://www.not-ads.adnetwork"></a>' + | 37 '<a id="non-ad-anchor" href="http://www.not-ads.adnetwork"></a>' + |
38 '<div id="empty-div"></div>'; | 38 '<div id="empty-div"></div>'; |
39 | 39 |
40 | |
41 | |
42 /** | 40 /** |
43 * The AdInjectorTest infrastructure. Basically, this allows the test to follow | 41 * The AdInjectorTest infrastructure. Basically, this allows the test to follow |
44 * a simple iteration cycle: | 42 * a simple iteration cycle: |
45 * - Signal the C++ test that we're going to do page setup, and we shouldn't | 43 * - Signal the C++ test that we're going to do page setup, and we shouldn't |
46 * record any ad-injector events (as some of the page setup could qualify). | 44 * record any ad-injector events (as some of the page setup could qualify). |
47 * - Do the page setup, which involves creating a 'playground' for ad injectors | 45 * - Do the page setup, which involves creating a 'playground' for ad injectors |
48 * of iframes, embeds, etc. See also ad_injectors.html. We do this set up for | 46 * of iframes, embeds, etc. See also ad_injectors.html. We do this set up for |
49 * each test, so that none of the tests conflicts with each other. | 47 * each test, so that none of the tests conflicts with each other. |
50 * - Signal that we are done with page setup, and should start recording events. | 48 * - Signal that we are done with page setup, and should start recording events. |
51 * - Run the next test. | 49 * - Run the next test. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 this.runNextFunction(); | 127 this.runNextFunction(); |
130 }.bind(this)); | 128 }.bind(this)); |
131 } | 129 } |
132 }; | 130 }; |
133 | 131 |
134 // Return values to signal the result of a test. Each test should return the | 132 // Return values to signal the result of a test. Each test should return the |
135 // appropriate value in order to indicate if an ad was injected, and, if so, | 133 // appropriate value in order to indicate if an ad was injected, and, if so, |
136 // what kind of injection. | 134 // what kind of injection. |
137 // These match the enum values in | 135 // These match the enum values in |
138 // chrome/browser/extensions/activity_log/activity_actions.h. | 136 // chrome/browser/extensions/activity_log/activity_actions.h. |
139 var NO_AD_INJECTION = 0; // The signal that there was no ad injection. | 137 // The signal that there was no ad injection. |
140 var INJECTION_NEW_AD = 1; // The signal that there was a new ad injected. | 138 var NO_AD_INJECTION = 0; |
141 var INJECTION_REMOVED_AD = 2; // The signal that an ad was removed. | 139 // The signal that there was a new ad injected. |
142 var INJECTION_REPLACED_AD = 3; // The signal that an ad was replaced. | 140 var INJECTION_NEW_AD = 1; |
| 141 // The signal that an ad was removed. |
| 142 var INJECTION_REMOVED_AD = 2; |
| 143 // The signal that an ad was replaced. |
| 144 var INJECTION_REPLACED_AD = 3; |
| 145 // The signal that an ad was likely replaced, but we didn't detect it fully. |
| 146 var INJECTION_LIKELY_REPLACED_AD = 4; |
143 | 147 |
144 /* The "ad network" url to use for tests. */ | 148 /* The "ad network" url to use for tests. */ |
145 var kAdNetwork = 'http://www.known-ads.adnetwork'; | 149 var kAdNetwork = 'http://www.known-ads.adnetwork'; |
| 150 var kAdNetwork2 = 'http://www.also-known-ads.adnetwork'; |
146 | 151 |
147 /* The "non ad network" url to use for tests. */ | 152 /* The "non ad network" url to use for tests. */ |
148 var kNonAdNetwork = 'http://www.not-ads.adnetwork'; | 153 var kNonAdNetwork = 'http://www.not-ads.adnetwork'; |
149 | 154 |
150 /* @return {?HTMLElement} The element with the given id. */ | 155 /* @return {?HTMLElement} The element with the given id. */ |
151 var $ = function(id) { return document.getElementById(id); } | 156 var $ = function(id) { return document.getElementById(id); } |
152 | 157 |
153 // The following is a collection of functions to "get" an HTML ad. We need to do | 158 // The following is a collection of functions to "get" an HTML ad. We need to do |
154 // this for internal counting in testing, because if we simply do: | 159 // this for internal counting in testing, because if we simply do: |
155 // var iframe = document.createElement('iframe'); | 160 // var iframe = document.createElement('iframe'); |
(...skipping 22 matching lines...) Expand all Loading... |
178 var kEmbedAdTemplate = document.createElement('embed'); | 183 var kEmbedAdTemplate = document.createElement('embed'); |
179 kEmbedAdTemplate.src = kAdNetwork; | 184 kEmbedAdTemplate.src = kAdNetwork; |
180 | 185 |
181 /** | 186 /** |
182 * @return An embed element which will count as ad injection in the tests. | 187 * @return An embed element which will count as ad injection in the tests. |
183 */ | 188 */ |
184 var getEmbedAd = function() { | 189 var getEmbedAd = function() { |
185 return kEmbedAdTemplate.cloneNode(true); | 190 return kEmbedAdTemplate.cloneNode(true); |
186 }; | 191 }; |
187 | 192 |
188 // Creates a link ad, like so: | 193 // Creates an anchor ad, like so: |
189 // <a href="http://www.known-ads.adnetwork"></a> | 194 // <a href="http://www.known-ads.adnetwork"></a> |
190 var kLinkAdTemplate = document.createElement('a'); | 195 var kAnchorAdTemplate = document.createElement('a'); |
191 kLinkAdTemplate.href = kAdNetwork; | 196 kAnchorAdTemplate.href = kAdNetwork; |
192 | 197 |
193 /** | 198 /** |
194 * @return A link ('a') element which will count as ad injection in the tests. | 199 * @return An anchor ('a') element which will count as ad injection in the |
| 200 * tests. |
195 */ | 201 */ |
196 var getLinkAd = function() { | 202 var getAnchorAd = function() { |
197 return kLinkAdTemplate.cloneNode(true); | 203 return kAnchorAdTemplate.cloneNode(true); |
198 }; | 204 }; |
199 | 205 |
200 // This series constructs a nested ad, which looks like this: | 206 // This series constructs a nested ad, which looks like this: |
201 // <div> | 207 // <div> |
202 // <div> | 208 // <div> |
203 // <span></span> | 209 // <span></span> |
204 // <iframe src="http://www.known-ads.adnetwork"></iframe> | 210 // <iframe src="http://www.known-ads.adnetwork"></iframe> |
205 // </div> | 211 // </div> |
206 // </div> | 212 // </div> |
207 var div = document.createElement('div'); | 213 var div = document.createElement('div'); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 functions.push(function NewIframeNonAdNetwork() { | 245 functions.push(function NewIframeNonAdNetwork() { |
240 var frame = document.createElement('iframe'); | 246 var frame = document.createElement('iframe'); |
241 frame.src = kNonAdNetwork; | 247 frame.src = kNonAdNetwork; |
242 document.body.appendChild(frame); | 248 document.body.appendChild(frame); |
243 return NO_AD_INJECTION; | 249 return NO_AD_INJECTION; |
244 }); | 250 }); |
245 | 251 |
246 // Modify an iframe which is currently in the DOM, switching the src to an | 252 // Modify an iframe which is currently in the DOM, switching the src to an |
247 // ad network. | 253 // ad network. |
248 functions.push(function ModifyExistingIframeToAdNetwork() { | 254 functions.push(function ModifyExistingIframeToAdNetwork() { |
249 var frame = $('ad-iframe'); | 255 var frame = $('non-ad-iframe'); |
250 frame.src = kAdNetwork; | 256 frame.src = kAdNetwork; |
251 return INJECTION_NEW_AD; | 257 return INJECTION_NEW_AD; |
252 }); | 258 }); |
253 | 259 |
254 // Add a new embed element which serves ads. | 260 // Add a new embed element which serves ads. |
255 functions.push(function NewEmbedAdNetwork() { | 261 functions.push(function NewEmbedAdNetwork() { |
256 document.body.appendChild(getEmbedAd()); | 262 document.body.appendChild(getEmbedAd()); |
257 return INJECTION_NEW_AD; | 263 return INJECTION_NEW_AD; |
258 }); | 264 }); |
259 | 265 |
260 // Add a new embed element which does not serve ads. We should not record | 266 // Add a new embed element which does not serve ads. We should not record |
261 // anything. | 267 // anything. |
262 functions.push(function NewEmbedNonAdNetwork() { | 268 functions.push(function NewEmbedNonAdNetwork() { |
263 var embed = document.createElement('embed'); | 269 var embed = document.createElement('embed'); |
264 embed.src = kNonAdNetwork; | 270 embed.src = kNonAdNetwork; |
265 document.body.appendChild(embed); | 271 document.body.appendChild(embed); |
266 return NO_AD_INJECTION; | 272 return NO_AD_INJECTION; |
267 }); | 273 }); |
268 | 274 |
269 // Modify an embed which is currently in the DOM, switching the src to an | 275 // Modify an embed which is currently in the DOM, switching the src to an |
270 // ad network. | 276 // ad network. |
271 functions.push(function ModifyExistingEmbedToAdNetwork() { | 277 functions.push(function ModifyExistingEmbedToAdNetwork() { |
272 var embed = $('ad-embed'); | 278 var embed = $('non-ad-embed'); |
273 embed.src = kAdNetwork; | 279 embed.src = kAdNetwork; |
274 return INJECTION_NEW_AD; | 280 return INJECTION_NEW_AD; |
275 }); | 281 }); |
276 | 282 |
277 // Add a new link element which serves ads. | 283 // Add a new anchor element which serves ads. |
278 functions.push(function NewLinkAd() { | 284 functions.push(function NewAnchorAd() { |
279 document.body.appendChild(getLinkAd()); | 285 document.body.appendChild(getAnchorAd()); |
280 return INJECTION_NEW_AD; | 286 return INJECTION_NEW_AD; |
281 }); | 287 }); |
282 | 288 |
| 289 functions.push(function NewAnchorNonAd() { |
| 290 var anchor = document.createElement('a'); |
| 291 anchor.src = kNonAdNetwork; |
| 292 document.body.appendChild(anchor); |
| 293 return NO_AD_INJECTION; |
| 294 }); |
| 295 |
| 296 functions.push(function ModifyExistingAnchorToAdNetwork() { |
| 297 var anchor = $('non-ad-anchor'); |
| 298 anchor.href = kAdNetwork; |
| 299 return INJECTION_NEW_AD; |
| 300 }); |
| 301 |
283 // Add a new element which has a nested ad, to ensure we do a deep check of | 302 // Add a new element which has a nested ad, to ensure we do a deep check of |
284 // elements appended to the dom. | 303 // elements appended to the dom. |
285 functions.push(function NewNestedAd() { | 304 functions.push(function NewNestedAd() { |
286 document.body.appendChild(getNestedAd()); | 305 document.body.appendChild(getNestedAd()); |
287 return INJECTION_NEW_AD; | 306 return INJECTION_NEW_AD; |
288 }); | 307 }); |
289 | 308 |
| 309 // Switch an existing embed ad to a new ad network. |
| 310 functions.push(function ReplaceEmbedAd() { |
| 311 $('ad-embed').src = kAdNetwork2; |
| 312 return INJECTION_REPLACED_AD; |
| 313 }); |
| 314 |
| 315 // Switch an existing iframe ad to a new ad network. |
| 316 functions.push(function ReplaceIframeAd() { |
| 317 $('ad-iframe').src = kAdNetwork2; |
| 318 return INJECTION_REPLACED_AD; |
| 319 }); |
| 320 |
| 321 // Switch an existing anchor ad to a new ad network. |
| 322 functions.push(function ReplaceAnchorAd() { |
| 323 $('ad-anchor').href = kAdNetwork2; |
| 324 return INJECTION_REPLACED_AD; |
| 325 }); |
| 326 |
| 327 // Remove an existing embed ad by setting it's src to a non-ad network. |
| 328 functions.push(function RemoveAdBySettingSrc() { |
| 329 $('ad-embed').src = kNonAdNetwork; |
| 330 return INJECTION_REMOVED_AD; |
| 331 }); |
| 332 |
| 333 // Ensure that we flag actions that look a lot like ad injection, even if we're |
| 334 // not sure. |
| 335 functions.push(function LikelyAdInjection() { |
| 336 // Switching from one valid url src to another valid url src is very |
| 337 // suspicious behavior, and should be relatively rare. This helps us determine |
| 338 // the effectiveness of our ad network recognition. |
| 339 $('non-ad-embed').src = 'http://www.thismightbeanadnetwork.ads'; |
| 340 return INJECTION_LIKELY_REPLACED_AD; |
| 341 }); |
| 342 |
290 // Verify that we do not enter the javascript world when we check for ad | 343 // Verify that we do not enter the javascript world when we check for ad |
291 // injection. | 344 // injection. |
292 functions.push(function VerifyNoAccess() { | 345 functions.push(function VerifyNoAccess() { |
293 var frame = document.createElement('iframe'); | 346 var frame = document.createElement('iframe'); |
294 frame.__defineGetter__('src', function() { | 347 frame.__defineGetter__('src', function() { |
295 throw new Error('Forbidden access into javascript execution!'); | 348 throw new Error('Forbidden access into javascript execution!'); |
296 return kAdNetwork; | 349 return kAdNetwork; |
297 }); | 350 }); |
298 return NO_AD_INJECTION; | 351 return NO_AD_INJECTION; |
299 }); | 352 }); |
300 | 353 |
301 // TODO(rdevlin.cronin): We are not covering every case yet. Fix this. | 354 // TODO(rdevlin.cronin): We are not covering every case yet. Fix this. |
302 // See crbug.com/357204. | 355 // See crbug.com/357204. |
303 | 356 |
304 // Kick off the tests. | 357 // Kick off the tests. |
305 var test = new AdInjectorTest(functions); | 358 var test = new AdInjectorTest(functions); |
306 test.runNextFunction(); | 359 test.runNextFunction(); |
OLD | NEW |