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

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: 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.
55 const char* kIframeElementType = "HTMLIFrameElement";
56 const char* kEmbedElementType = "HTMLEmbedElement";
57 const char* kAnchorElementType = "HTMLAnchorElement";
58
59 std::string Serialize(const base::Value* value) { 44 std::string Serialize(const base::Value* value) {
60 std::string value_as_text; 45 std::string value_as_text;
61 if (!value) { 46 if (!value) {
62 value_as_text = "null"; 47 value_as_text = "null";
63 } else { 48 } else {
64 JSONStringValueSerializer serializer(&value_as_text); 49 JSONStringValueSerializer serializer(&value_as_text);
65 serializer.SerializeAndOmitBinaryValues(*value); 50 serializer.SerializeAndOmitBinaryValues(*value);
66 } 51 }
67 return value_as_text; 52 return value_as_text;
68 } 53 }
69 54
70 } // namespace 55 } // namespace
71 56
57 namespace ad_injection_constants {
Devlin 2014/07/15 17:21:52 nit: I think we can just take out the namespace an
pmarch 2014/07/16 10:34:17 Done.
58
59 const char kBlinkSetAttributeEvent[] = "blinkSetAttribute";
60 const char kBlinkAddElementEvent[] = "blinkAddElement";
61
62 const char kIframe[] = "iframe";
63 const char kAnchor[] = "a";
64
65 const char kSrc[] = "src";
66 const char kHref[] = "href";
67
68 } // namespace ad_injection_constants
69
72 using api::activity_log_private::ExtensionActivity; 70 using api::activity_log_private::ExtensionActivity;
73 71
74 Action::Action(const std::string& extension_id, 72 Action::Action(const std::string& extension_id,
75 const base::Time& time, 73 const base::Time& time,
76 const ActionType action_type, 74 const ActionType action_type,
77 const std::string& api_name, 75 const std::string& api_name,
78 int64 action_id) 76 int64 action_id)
79 : extension_id_(extension_id), 77 : extension_id_(extension_id),
80 time_(time), 78 time_(time),
81 action_type_(action_type), 79 action_type_(action_type),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 // We should always have an AdNetworkDatabase, but, on the offchance we don't, 111 // We should always have an AdNetworkDatabase, but, on the offchance we don't,
114 // don't crash in a release build. 112 // don't crash in a release build.
115 if (!AdNetworkDatabase::Get()) { 113 if (!AdNetworkDatabase::Get()) {
116 NOTREACHED(); 114 NOTREACHED();
117 return NO_AD_INJECTION; 115 return NO_AD_INJECTION;
118 } 116 }
119 117
120 AdType ad_type = AD_TYPE_NONE; 118 AdType ad_type = AD_TYPE_NONE;
121 InjectionType injection_type = NO_AD_INJECTION; 119 InjectionType injection_type = NO_AD_INJECTION;
122 120
123 if (EndsWith(api_name_, 121 if (api_name_ == ad_injection_constants::kBlinkSetAttributeEvent) {
124 ad_injection_constants::kAppendChildApiSuffix, 122 std::string element_name;
125 true /* case senstive */)) { 123 std::string attr_name;
126 injection_type = CheckAppendChild(&ad_type); 124 if (args_.get()) {
127 } else { 125 args_->GetString(0u, &element_name);
128 // Check if the action modified an element's src/href. 126 args_->GetString(1u, &attr_name);
129 if (api_name_ == ad_injection_constants::kHtmlIframeSrcApiName) 127 }
128 if (element_name == ad_injection_constants::kIframe &&
129 attr_name == ad_injection_constants::kSrc)
130 ad_type = AD_TYPE_IFRAME; 130 ad_type = AD_TYPE_IFRAME;
131 else if (api_name_ == ad_injection_constants::kHtmlEmbedSrcApiName) 131 else if (element_name == ad_injection_constants::kAnchor &&
132 ad_type = AD_TYPE_EMBED; 132 attr_name == ad_injection_constants::kHref)
133 else if (api_name_ == ad_injection_constants::kHtmlAnchorHrefApiName)
134 ad_type = AD_TYPE_ANCHOR; 133 ad_type = AD_TYPE_ANCHOR;
135 134
136 if (ad_type != AD_TYPE_NONE) 135 if (ad_type != AD_TYPE_NONE)
137 injection_type = CheckSrcModification(); 136 injection_type = CheckAttrModification();
137 } else if (api_name_ == ad_injection_constants::kBlinkAddElementEvent) {
138 std::string element_name;
139 if (args_.get())
140 args_->GetString(0u, &element_name);
141 if (element_name == ad_injection_constants::kIframe)
142 ad_type = AD_TYPE_IFRAME;
143 else if (element_name == ad_injection_constants::kAnchor)
144 ad_type = AD_TYPE_ANCHOR;
145
146 if (ad_type != AD_TYPE_NONE)
147 injection_type = CheckElementAddition();
138 } 148 }
139 149
140 if (injection_type != NO_AD_INJECTION) { 150 if (injection_type != NO_AD_INJECTION) {
141 UMA_HISTOGRAM_ENUMERATION( 151 UMA_HISTOGRAM_ENUMERATION(
142 "Extensions.AdInjection.AdType", ad_type, Action::NUM_AD_TYPES); 152 "Extensions.AdInjection.AdType", ad_type, Action::NUM_AD_TYPES);
143 } 153 }
144 154
145 return injection_type; 155 return injection_type;
146 } 156 }
147 157
(...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 376 // current page should be considered valid use), and aren't local to the
367 // extension. 377 // extension.
368 return url.is_valid() && 378 return url.is_valid() &&
369 !url.is_empty() && 379 !url.is_empty() &&
370 url.host() != page_url_.host() && 380 url.host() != page_url_.host() &&
371 !url.SchemeIs(kExtensionScheme); 381 !url.SchemeIs(kExtensionScheme);
372 } 382 }
373 383
374 void Action::MaybeUploadUrl(rappor::RapporService* rappor_service) const { 384 void Action::MaybeUploadUrl(rappor::RapporService* rappor_service) const {
375 // Don't bother recording if the url is innocuous (or no |rappor_service|). 385 // Don't bother recording if the url is innocuous (or no |rappor_service|).
376 if (!rappor_service || !UrlCouldBeAd(arg_url_)) 386 if (!rappor_service)
377 return; 387 return;
378 388
379 bool can_inject_ads = false; 389 GURL url;
380 for (size_t i = 0; i < arraysize(kApisForRapporMetric); ++i) { 390
381 if (api_name_ == kApisForRapporMetric[i]) { 391 if (api_name_ == ad_injection_constants::kBlinkSetAttributeEvent) {
382 can_inject_ads = true; 392 std::string element_name;
383 break; 393 std::string attr_name;
394 std::string url_string;
395 if (args_.get()) {
396 args_->GetString(0u, &element_name);
397 args_->GetString(1u, &attr_name);
398 }
399 if (element_name == ad_injection_constants::kIframe &&
400 attr_name == ad_injection_constants::kSrc) {
401 args_->GetString(3u, &url_string);
402 url = GURL(url_string);
403 } else if (element_name == ad_injection_constants::kAnchor &&
404 attr_name == ad_injection_constants::kHref) {
405 args_->GetString(3u, &url_string);
406 url = GURL(url_string);
407 }
408 } else if (api_name_ == ad_injection_constants::kBlinkAddElementEvent) {
409 std::string element_name;
410 std::string url_string;
411 if (args_.get())
412 args_->GetString(0u, &element_name);
413 if (element_name == ad_injection_constants::kIframe) {
414 args_->GetString(1u, &url_string);
415 url = GURL(url_string);
416 } else if (element_name == ad_injection_constants::kAnchor) {
417 args_->GetString(1u, &url_string);
418 url = GURL(url_string);
384 } 419 }
385 } 420 }
386 421
387 if (!can_inject_ads) 422 if (!UrlCouldBeAd(url))
388 return; 423 return;
389 424
390 // Record the URL - an ad *may* have been injected. 425 // Record the URL - an ad *may* have been injected.
391 rappor_service->RecordSample(kExtensionAdInjectionRapporMetricName, 426 rappor_service->RecordSample(kExtensionAdInjectionRapporMetricName,
392 rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, 427 rappor::ETLD_PLUS_ONE_RAPPOR_TYPE,
393 arg_url_.host()); 428 url.host());
394 } 429 }
395 430
396 Action::InjectionType Action::CheckSrcModification() const { 431 Action::InjectionType Action::CheckAttrModification() const {
432 if (api_name_ != ad_injection_constants::kBlinkSetAttributeEvent)
433 return NO_AD_INJECTION;
434
397 const AdNetworkDatabase* database = AdNetworkDatabase::Get(); 435 const AdNetworkDatabase* database = AdNetworkDatabase::Get();
398 436
399 bool arg_url_could_be_ad = UrlCouldBeAd(arg_url_);
400
401 GURL prev_url; 437 GURL prev_url;
402 std::string prev_url_string; 438 std::string prev_url_string;
403 if (args_.get() && args_->GetString(1u, &prev_url_string)) 439 if (args_.get() && args_->GetString(2u, &prev_url_string))
404 prev_url = GURL(prev_url_string); 440 prev_url = GURL(prev_url_string);
405 441
442 GURL url;
443 std::string url_string;
444 if (args_.get() && args_->GetString(3u, &url_string))
445 url = GURL(url_string);
446
447 bool arg_url_could_be_ad = UrlCouldBeAd(url);
Devlin 2014/07/15 17:21:52 nit: this is no longer the |arg_url_|, so we shoul
pmarch 2014/07/16 10:34:17 Done.
406 bool prev_url_valid = prev_url.is_valid() && !prev_url.is_empty(); 448 bool prev_url_valid = prev_url.is_valid() && !prev_url.is_empty();
407 449
408 bool injected_ad = arg_url_could_be_ad && database->IsAdNetwork(arg_url_); 450 bool injected_ad = arg_url_could_be_ad && database->IsAdNetwork(url);
409 bool replaced_ad = prev_url_valid && database->IsAdNetwork(prev_url); 451 bool replaced_ad = prev_url_valid && database->IsAdNetwork(prev_url);
410 452
411 if (injected_ad && replaced_ad) 453 if (injected_ad && replaced_ad)
412 return INJECTION_REPLACED_AD; 454 return INJECTION_REPLACED_AD;
413 if (injected_ad) 455 if (injected_ad)
414 return INJECTION_NEW_AD; 456 return INJECTION_NEW_AD;
415 if (replaced_ad) 457 if (replaced_ad)
416 return INJECTION_REMOVED_AD; 458 return INJECTION_REMOVED_AD;
417 459
418 // If the extension modified the URL with an external, valid URL then there's 460 // 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 461 // 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. 462 // us determine the effectiveness of our IsAdNetwork() recognition.
421 if (arg_url_could_be_ad) { 463 if (arg_url_could_be_ad) {
422 if (prev_url_valid) 464 if (prev_url_valid)
423 return INJECTION_LIKELY_REPLACED_AD; 465 return INJECTION_LIKELY_REPLACED_AD;
424 return INJECTION_LIKELY_NEW_AD; 466 return INJECTION_LIKELY_NEW_AD;
425 } 467 }
426 468
427 return NO_AD_INJECTION; 469 return NO_AD_INJECTION;
428 } 470 }
429 471
430 Action::InjectionType Action::CheckAppendChild(AdType* ad_type_out) const { 472 Action::InjectionType Action::CheckElementAddition() const {
431 const base::DictionaryValue* child = NULL; 473 if (api_name_ != ad_injection_constants::kBlinkAddElementEvent)
432 if (!args_->GetDictionary(0u, &child))
433 return NO_AD_INJECTION; 474 return NO_AD_INJECTION;
434 475
435 return CheckDomObject(child, ad_type_out); 476 GURL url;
436 } 477 std::string url_string;
478 if (args_.get() && args_->GetString(1u, &url_string))
479 url = GURL(url_string);
437 480
438 Action::InjectionType Action::CheckDomObject( 481 if (UrlCouldBeAd(url)) {
439 const base::DictionaryValue* object, 482 if (AdNetworkDatabase::Get()->IsAdNetwork(url))
440 AdType* ad_type_out) const { 483 return INJECTION_NEW_AD;
441 DCHECK(ad_type_out); 484 // If the extension injected an URL which is not local to itself or the
442 std::string type; 485 // page, there is a good chance it could be a new ad, and our database
443 object->GetString(keys::kType, &type); 486 // missed it.
444 487 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 } 488 }
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; 489 return NO_AD_INJECTION;
490 } 490 }
491 491
492 bool ActionComparator::operator()( 492 bool ActionComparator::operator()(
493 const scoped_refptr<Action>& lhs, 493 const scoped_refptr<Action>& lhs,
494 const scoped_refptr<Action>& rhs) const { 494 const scoped_refptr<Action>& rhs) const {
495 if (lhs->time() != rhs->time()) 495 if (lhs->time() != rhs->time())
496 return lhs->time() < rhs->time(); 496 return lhs->time() < rhs->time();
497 else if (lhs->action_id() != rhs->action_id()) 497 else if (lhs->action_id() != rhs->action_id())
498 return lhs->action_id() < rhs->action_id(); 498 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()); 547 std::string rhs_other = ActivityLogPolicy::Util::Serialize(rhs->other());
548 if (lhs_other != rhs_other) 548 if (lhs_other != rhs_other)
549 return lhs_other < rhs_other; 549 return lhs_other < rhs_other;
550 } 550 }
551 551
552 // All fields compare as equal if this point is reached. 552 // All fields compare as equal if this point is reached.
553 return false; 553 return false;
554 } 554 }
555 555
556 } // namespace extensions 556 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698