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

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

Issue 384983003: Enabling AdInjectionBrowserTest after Activity Log refactoring. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comment Created 6 years, 5 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 (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "chrome/browser/extensions/activity_log/activity_actions.h" 5 #include "chrome/browser/extensions/activity_log/activity_actions.h"
6 6
7 #include <algorithm> // for std::find. 7 #include <algorithm> // for std::find.
8 #include <string> 8 #include <string>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/format_macros.h" 11 #include "base/format_macros.h"
12 #include "base/json/json_string_value_serializer.h" 12 #include "base/json/json_string_value_serializer.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/singleton.h" 15 #include "base/memory/singleton.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
20 #include "base/values.h" 20 #include "base/values.h"
21 #include "chrome/browser/extensions/activity_log/activity_action_constants.h" 21 #include "chrome/browser/extensions/activity_log/activity_action_constants.h"
22 #include "chrome/browser/extensions/activity_log/ad_network_database.h" 22 #include "chrome/browser/extensions/activity_log/ad_network_database.h"
23 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h" 23 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
24 #include "chrome/browser/ui/browser.h" 24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/common/chrome_switches.h" 25 #include "chrome/common/chrome_switches.h"
26 #include "components/rappor/rappor_service.h" 26 #include "components/rappor/rappor_service.h"
27 #include "content/public/browser/web_contents.h" 27 #include "content/public/browser/web_contents.h"
28 #include "extensions/common/ad_injection_constants.h"
29 #include "extensions/common/constants.h" 28 #include "extensions/common/constants.h"
30 #include "extensions/common/dom_action_types.h" 29 #include "extensions/common/dom_action_types.h"
31 #include "sql/statement.h" 30 #include "sql/statement.h"
32 #include "url/gurl.h" 31 #include "url/gurl.h"
33 32
34 namespace constants = activity_log_constants; 33 namespace constants = activity_log_constants;
35 34
36 namespace extensions { 35 namespace extensions {
37 36
38 namespace { 37 namespace {
39 38
40 namespace keys = ad_injection_constants::keys;
41
42 // The list of APIs for which we upload the URL to RAPPOR.
43 const char* kApisForRapporMetric[] = {
44 ad_injection_constants::kHtmlIframeSrcApiName,
45 ad_injection_constants::kHtmlEmbedSrcApiName,
46 ad_injection_constants::kHtmlAnchorHrefApiName
47 };
48
49 // The "Extensions.PossibleAdInjection2" metric uses different Rappor 39 // The "Extensions.PossibleAdInjection2" metric uses different Rappor
50 // parameters than the original metric. 40 // parameters than the original metric.
51 const char* kExtensionAdInjectionRapporMetricName = 41 const char* kExtensionAdInjectionRapporMetricName =
52 "Extensions.PossibleAdInjection2"; 42 "Extensions.PossibleAdInjection2";
53 43
54 // The names of different types of HTML elements we check for ad injection. 44 const char kBlinkSetAttributeEvent[] = "blinkSetAttribute";
55 const char* kIframeElementType = "HTMLIFrameElement"; 45 const char kBlinkAddElementEvent[] = "blinkAddElement";
56 const char* kEmbedElementType = "HTMLEmbedElement"; 46
57 const char* kAnchorElementType = "HTMLAnchorElement"; 47 const char kIframe[] = "iframe";
48 const char kAnchor[] = "a";
49
50 const char kSrc[] = "src";
51 const char kHref[] = "href";
58 52
59 std::string Serialize(const base::Value* value) { 53 std::string Serialize(const base::Value* value) {
60 std::string value_as_text; 54 std::string value_as_text;
61 if (!value) { 55 if (!value) {
62 value_as_text = "null"; 56 value_as_text = "null";
63 } else { 57 } else {
64 JSONStringValueSerializer serializer(&value_as_text); 58 JSONStringValueSerializer serializer(&value_as_text);
65 serializer.SerializeAndOmitBinaryValues(*value); 59 serializer.SerializeAndOmitBinaryValues(*value);
66 } 60 }
67 return value_as_text; 61 return value_as_text;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 // We should always have an AdNetworkDatabase, but, on the offchance we don't, 107 // We should always have an AdNetworkDatabase, but, on the offchance we don't,
114 // don't crash in a release build. 108 // don't crash in a release build.
115 if (!AdNetworkDatabase::Get()) { 109 if (!AdNetworkDatabase::Get()) {
116 NOTREACHED(); 110 NOTREACHED();
117 return NO_AD_INJECTION; 111 return NO_AD_INJECTION;
118 } 112 }
119 113
120 AdType ad_type = AD_TYPE_NONE; 114 AdType ad_type = AD_TYPE_NONE;
121 InjectionType injection_type = NO_AD_INJECTION; 115 InjectionType injection_type = NO_AD_INJECTION;
122 116
123 if (EndsWith(api_name_, 117 if (api_name_ == kBlinkSetAttributeEvent) {
124 ad_injection_constants::kAppendChildApiSuffix, 118 std::string element_name;
125 true /* case senstive */)) { 119 std::string attr_name;
126 injection_type = CheckAppendChild(&ad_type); 120 if (args_.get()) {
127 } else { 121 args_->GetString(0u, &element_name);
128 // Check if the action modified an element's src/href. 122 args_->GetString(1u, &attr_name);
129 if (api_name_ == ad_injection_constants::kHtmlIframeSrcApiName) 123 }
124 if (element_name == kIframe && attr_name == kSrc)
130 ad_type = AD_TYPE_IFRAME; 125 ad_type = AD_TYPE_IFRAME;
131 else if (api_name_ == ad_injection_constants::kHtmlEmbedSrcApiName) 126 else if (element_name == kAnchor && attr_name == kHref)
132 ad_type = AD_TYPE_EMBED;
133 else if (api_name_ == ad_injection_constants::kHtmlAnchorHrefApiName)
134 ad_type = AD_TYPE_ANCHOR; 127 ad_type = AD_TYPE_ANCHOR;
135 128
136 if (ad_type != AD_TYPE_NONE) 129 if (ad_type != AD_TYPE_NONE)
137 injection_type = CheckSrcModification(); 130 injection_type = CheckAttrModification();
131 } else if (api_name_ == kBlinkAddElementEvent) {
132 std::string element_name;
133 if (args_.get())
134 args_->GetString(0u, &element_name);
135 if (element_name == kIframe)
136 ad_type = AD_TYPE_IFRAME;
137 else if (element_name == kAnchor)
138 ad_type = AD_TYPE_ANCHOR;
139
140 if (ad_type != AD_TYPE_NONE)
141 injection_type = CheckElementAddition();
138 } 142 }
139 143
140 if (injection_type != NO_AD_INJECTION) { 144 if (injection_type != NO_AD_INJECTION) {
141 UMA_HISTOGRAM_ENUMERATION( 145 UMA_HISTOGRAM_ENUMERATION(
142 "Extensions.AdInjection.AdType", ad_type, Action::NUM_AD_TYPES); 146 "Extensions.AdInjection.AdType", ad_type, Action::NUM_AD_TYPES);
143 } 147 }
144 148
145 return injection_type; 149 return injection_type;
146 } 150 }
147 151
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 // current page should be considered valid use), and aren't local to the 370 // current page should be considered valid use), and aren't local to the
367 // extension. 371 // extension.
368 return url.is_valid() && 372 return url.is_valid() &&
369 !url.is_empty() && 373 !url.is_empty() &&
370 url.host() != page_url_.host() && 374 url.host() != page_url_.host() &&
371 !url.SchemeIs(kExtensionScheme); 375 !url.SchemeIs(kExtensionScheme);
372 } 376 }
373 377
374 void Action::MaybeUploadUrl(rappor::RapporService* rappor_service) const { 378 void Action::MaybeUploadUrl(rappor::RapporService* rappor_service) const {
375 // Don't bother recording if the url is innocuous (or no |rappor_service|). 379 // Don't bother recording if the url is innocuous (or no |rappor_service|).
376 if (!rappor_service || !UrlCouldBeAd(arg_url_)) 380 if (!rappor_service)
377 return; 381 return;
378 382
379 bool can_inject_ads = false; 383 GURL url;
380 for (size_t i = 0; i < arraysize(kApisForRapporMetric); ++i) { 384
381 if (api_name_ == kApisForRapporMetric[i]) { 385 if (api_name_ == kBlinkSetAttributeEvent) {
382 can_inject_ads = true; 386 std::string element_name;
383 break; 387 std::string attr_name;
388 std::string url_string;
389 if (args_.get()) {
390 args_->GetString(0u, &element_name);
391 args_->GetString(1u, &attr_name);
392 }
393 if (element_name == kIframe && attr_name == kSrc) {
394 args_->GetString(3u, &url_string);
395 url = GURL(url_string);
396 } else if (element_name == kAnchor && attr_name == kHref) {
397 args_->GetString(3u, &url_string);
398 url = GURL(url_string);
399 }
400 } else if (api_name_ == kBlinkAddElementEvent) {
401 std::string element_name;
402 std::string url_string;
403 if (args_.get())
404 args_->GetString(0u, &element_name);
405 if (element_name == kIframe) {
406 args_->GetString(1u, &url_string);
407 url = GURL(url_string);
408 } else if (element_name == kAnchor) {
409 args_->GetString(1u, &url_string);
410 url = GURL(url_string);
384 } 411 }
385 } 412 }
386 413
387 if (!can_inject_ads) 414 if (!UrlCouldBeAd(url))
388 return; 415 return;
389 416
390 // Record the URL - an ad *may* have been injected. 417 // Record the URL - an ad *may* have been injected.
391 rappor_service->RecordSample(kExtensionAdInjectionRapporMetricName, 418 rappor_service->RecordSample(kExtensionAdInjectionRapporMetricName,
392 rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, 419 rappor::ETLD_PLUS_ONE_RAPPOR_TYPE,
393 arg_url_.host()); 420 url.host());
394 } 421 }
395 422
396 Action::InjectionType Action::CheckSrcModification() const { 423 Action::InjectionType Action::CheckAttrModification() const {
424 if (api_name_ != kBlinkSetAttributeEvent)
425 return NO_AD_INJECTION;
426
397 const AdNetworkDatabase* database = AdNetworkDatabase::Get(); 427 const AdNetworkDatabase* database = AdNetworkDatabase::Get();
398 428
399 bool arg_url_could_be_ad = UrlCouldBeAd(arg_url_);
400
401 GURL prev_url; 429 GURL prev_url;
402 std::string prev_url_string; 430 std::string prev_url_string;
403 if (args_.get() && args_->GetString(1u, &prev_url_string)) 431 if (args_.get() && args_->GetString(2u, &prev_url_string))
404 prev_url = GURL(prev_url_string); 432 prev_url = GURL(prev_url_string);
405 433
434 GURL new_url;
435 std::string new_url_string;
436 if (args_.get() && args_->GetString(3u, &new_url_string))
437 new_url = GURL(new_url_string);
438
439 bool new_url_could_be_ad = UrlCouldBeAd(new_url);
406 bool prev_url_valid = prev_url.is_valid() && !prev_url.is_empty(); 440 bool prev_url_valid = prev_url.is_valid() && !prev_url.is_empty();
407 441
408 bool injected_ad = arg_url_could_be_ad && database->IsAdNetwork(arg_url_); 442 bool injected_ad = new_url_could_be_ad && database->IsAdNetwork(new_url);
409 bool replaced_ad = prev_url_valid && database->IsAdNetwork(prev_url); 443 bool replaced_ad = prev_url_valid && database->IsAdNetwork(prev_url);
410 444
411 if (injected_ad && replaced_ad) 445 if (injected_ad && replaced_ad)
412 return INJECTION_REPLACED_AD; 446 return INJECTION_REPLACED_AD;
413 if (injected_ad) 447 if (injected_ad)
414 return INJECTION_NEW_AD; 448 return INJECTION_NEW_AD;
415 if (replaced_ad) 449 if (replaced_ad)
416 return INJECTION_REMOVED_AD; 450 return INJECTION_REMOVED_AD;
417 451
418 // If the extension modified the URL with an external, valid URL then there's 452 // If the extension modified the URL with an external, valid URL then there's
419 // a good chance it's ad injection. Log it as a likely one, which also helps 453 // a good chance it's ad injection. Log it as a likely one, which also helps
420 // us determine the effectiveness of our IsAdNetwork() recognition. 454 // us determine the effectiveness of our IsAdNetwork() recognition.
421 if (arg_url_could_be_ad) { 455 if (new_url_could_be_ad) {
422 if (prev_url_valid) 456 if (prev_url_valid)
423 return INJECTION_LIKELY_REPLACED_AD; 457 return INJECTION_LIKELY_REPLACED_AD;
424 return INJECTION_LIKELY_NEW_AD; 458 return INJECTION_LIKELY_NEW_AD;
425 } 459 }
426 460
427 return NO_AD_INJECTION; 461 return NO_AD_INJECTION;
428 } 462 }
429 463
430 Action::InjectionType Action::CheckAppendChild(AdType* ad_type_out) const { 464 Action::InjectionType Action::CheckElementAddition() const {
431 const base::DictionaryValue* child = NULL; 465 if (api_name_ != kBlinkAddElementEvent)
432 if (!args_->GetDictionary(0u, &child))
433 return NO_AD_INJECTION; 466 return NO_AD_INJECTION;
434 467
435 return CheckDomObject(child, ad_type_out); 468 GURL url;
436 } 469 std::string url_string;
470 if (args_.get() && args_->GetString(1u, &url_string))
471 url = GURL(url_string);
437 472
438 Action::InjectionType Action::CheckDomObject( 473 if (UrlCouldBeAd(url)) {
439 const base::DictionaryValue* object, 474 if (AdNetworkDatabase::Get()->IsAdNetwork(url))
440 AdType* ad_type_out) const { 475 return INJECTION_NEW_AD;
441 DCHECK(ad_type_out); 476 // If the extension injected an URL which is not local to itself or the
442 std::string type; 477 // page, there is a good chance it could be a new ad, and our database
443 object->GetString(keys::kType, &type); 478 // missed it.
444 479 return INJECTION_LIKELY_NEW_AD;
445 AdType ad_type = AD_TYPE_NONE;
446 std::string url_key;
447 if (type == kIframeElementType) {
448 ad_type = AD_TYPE_IFRAME;
449 url_key = keys::kSrc;
450 } else if (type == kEmbedElementType) {
451 ad_type = AD_TYPE_EMBED;
452 url_key = keys::kSrc;
453 } else if (type == kAnchorElementType) {
454 ad_type = AD_TYPE_ANCHOR;
455 url_key = keys::kHref;
456 } 480 }
457
458 if (!url_key.empty()) {
459 std::string url;
460 if (object->GetString(url_key, &url)) {
461 GURL gurl(url);
462 if (UrlCouldBeAd(gurl)) {
463 *ad_type_out = ad_type;
464 if (AdNetworkDatabase::Get()->IsAdNetwork(gurl))
465 return INJECTION_NEW_AD;
466 // If the extension injected an URL which is not local to itself or the
467 // page, there is a good chance it could be a new ad, and our database
468 // missed it.
469 return INJECTION_LIKELY_NEW_AD;
470 }
471 }
472 }
473
474 const base::ListValue* children = NULL;
475 if (object->GetList(keys::kChildren, &children)) {
476 const base::DictionaryValue* child = NULL;
477 for (size_t i = 0;
478 i < children->GetSize() &&
479 i < ad_injection_constants::kMaximumChildrenToCheck;
480 ++i) {
481 if (children->GetDictionary(i, &child)) {
482 InjectionType type = CheckDomObject(child, ad_type_out);
483 if (type != NO_AD_INJECTION)
484 return type;
485 }
486 }
487 }
488
489 return NO_AD_INJECTION; 481 return NO_AD_INJECTION;
490 } 482 }
491 483
492 bool ActionComparator::operator()( 484 bool ActionComparator::operator()(
493 const scoped_refptr<Action>& lhs, 485 const scoped_refptr<Action>& lhs,
494 const scoped_refptr<Action>& rhs) const { 486 const scoped_refptr<Action>& rhs) const {
495 if (lhs->time() != rhs->time()) 487 if (lhs->time() != rhs->time())
496 return lhs->time() < rhs->time(); 488 return lhs->time() < rhs->time();
497 else if (lhs->action_id() != rhs->action_id()) 489 else if (lhs->action_id() != rhs->action_id())
498 return lhs->action_id() < rhs->action_id(); 490 return lhs->action_id() < rhs->action_id();
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 std::string rhs_other = ActivityLogPolicy::Util::Serialize(rhs->other()); 539 std::string rhs_other = ActivityLogPolicy::Util::Serialize(rhs->other());
548 if (lhs_other != rhs_other) 540 if (lhs_other != rhs_other)
549 return lhs_other < rhs_other; 541 return lhs_other < rhs_other;
550 } 542 }
551 543
552 // All fields compare as equal if this point is reached. 544 // All fields compare as equal if this point is reached.
553 return false; 545 return false;
554 } 546 }
555 547
556 } // namespace extensions 548 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698