Index: chrome/browser/safe_browsing/client_side_detection_host.cc |
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc |
index 3cd96a574dfe508a84b6d12cc3e9a7c6c1cb0bf3..146af774ee0e4d177507042758e3231f91c2c8f7 100644 |
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc |
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc |
@@ -269,7 +269,8 @@ ClientSideDetectionHost* ClientSideDetectionHost::Create( |
ClientSideDetectionHost::ClientSideDetectionHost(TabContents* tab) |
: TabContentsObserver(tab), |
csd_service_(NULL), |
- cb_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
+ cb_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
+ unsafe_unique_page_id_(-1) { |
DCHECK(tab); |
csd_service_ = g_browser_process->safe_browsing_detection_service(); |
feature_extractor_.reset(new BrowserFeatureExtractor(tab, csd_service_)); |
@@ -277,15 +278,22 @@ ClientSideDetectionHost::ClientSideDetectionHost(TabContents* tab) |
// Note: csd_service_ and sb_service_ will be NULL here in testing. |
registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED, |
Source<RenderViewHostDelegate>(tab)); |
+ if (sb_service_) { |
+ sb_service_->AddObserver(this); |
+ } |
} |
-ClientSideDetectionHost::~ClientSideDetectionHost() {} |
+ClientSideDetectionHost::~ClientSideDetectionHost() { |
+ if (sb_service_) { |
+ sb_service_->RemoveObserver(this); |
+ } |
+} |
bool ClientSideDetectionHost::OnMessageReceived(const IPC::Message& message) { |
bool handled = true; |
IPC_BEGIN_MESSAGE_MAP(ClientSideDetectionHost, message) |
- IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_DetectedPhishingSite, |
- OnDetectedPhishingSite) |
+ IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone, |
+ OnPhishingDetectionDone) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP() |
return handled; |
@@ -329,6 +337,24 @@ void ClientSideDetectionHost::DidNavigateMainFramePostCommit( |
classification_request_->Start(); |
} |
+void ClientSideDetectionHost::OnSafeBrowsingHit( |
+ const SafeBrowsingService::UnsafeResource& resource) { |
+ // Check that this notification is really for us and that it corresponds to |
+ // either a malware or phishing hit. In this case we store the unique page |
+ // ID for later. |
+ if (tab_contents() && |
+ tab_contents()->GetRenderProcessHost()->id() == |
+ resource.render_process_host_id && |
+ tab_contents()->render_view_host()->routing_id() == |
+ resource.render_view_id && |
+ (resource.threat_type == SafeBrowsingService::URL_PHISHING || |
+ resource.threat_type == SafeBrowsingService::URL_MALWARE) && |
+ tab_contents()->controller().GetActiveEntry()) { |
+ unsafe_unique_page_id_ = |
+ tab_contents()->controller().GetActiveEntry()->unique_id(); |
+ } |
+} |
+ |
void ClientSideDetectionHost::TabContentsDestroyed(TabContents* tab) { |
DCHECK(tab); |
// Tell any pending classification request that it is being canceled. |
@@ -339,7 +365,7 @@ void ClientSideDetectionHost::TabContentsDestroyed(TabContents* tab) { |
feature_extractor_.reset(); |
} |
-void ClientSideDetectionHost::OnDetectedPhishingSite( |
+void ClientSideDetectionHost::OnPhishingDetectionDone( |
const std::string& verdict_str) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// There is something seriously wrong if there is no service class but |
@@ -358,7 +384,12 @@ void ClientSideDetectionHost::OnDetectedPhishingSite( |
!cb_factory_.HasPendingCallbacks() && |
browse_info_.get() && |
verdict->ParseFromString(verdict_str) && |
- verdict->IsInitialized()) { |
+ verdict->IsInitialized() && |
+ // We only send the verdict to the server if the verdict is phishing or if |
+ // a SafeBrowsing interstitial was already shown for this site. E.g., a |
+ // malware or phishing interstitial was shown but the user clicked |
+ // through. |
+ (verdict->is_phishing() || DidShowSBInterstitial())) { |
// Start browser-side feature extraction. Once we're done it will send |
// the client verdict request. |
feature_extractor_->ExtractFeatures( |
@@ -406,11 +437,17 @@ void ClientSideDetectionHost::FeatureExtractionDone( |
} |
VLOG(2) << "Feature extraction done (success:" << success << ") for URL: " |
<< request->url() << ". Start sending client phishing request."; |
- // Send ping no matter what - even if the browser feature extraction failed. |
+ ClientSideDetectionService::ClientReportPhishingRequestCallback* cb = NULL; |
+ // If the client-side verdict isn't phishing we don't care about the server |
+ // response because we aren't going to display a warning. |
+ if (request->is_phishing()) { |
+ cb = cb_factory_.NewCallback( |
+ &ClientSideDetectionHost::MaybeShowPhishingWarning); |
+ } |
+ // Send ping even if the browser feature extraction failed. |
csd_service_->SendClientReportPhishingRequest( |
request, // The service takes ownership of the request object. |
- cb_factory_.NewCallback( |
- &ClientSideDetectionHost::MaybeShowPhishingWarning)); |
+ cb); |
} |
void ClientSideDetectionHost::Observe(int type, |
@@ -425,6 +462,15 @@ void ClientSideDetectionHost::Observe(int type, |
} |
} |
+bool ClientSideDetectionHost::DidShowSBInterstitial() { |
+ if (unsafe_unique_page_id_ <= 0 || !tab_contents()) { |
+ return false; |
+ } |
+ const NavigationEntry* nav_entry = |
+ tab_contents()->controller().GetActiveEntry(); |
+ return (nav_entry && nav_entry->unique_id() == unsafe_unique_page_id_); |
+} |
+ |
void ClientSideDetectionHost::set_client_side_detection_service( |
ClientSideDetectionService* service) { |
csd_service_ = service; |
@@ -432,7 +478,13 @@ void ClientSideDetectionHost::set_client_side_detection_service( |
void ClientSideDetectionHost::set_safe_browsing_service( |
SafeBrowsingService* service) { |
+ if (sb_service_) { |
+ sb_service_->RemoveObserver(this); |
+ } |
sb_service_ = service; |
+ if (sb_service_) { |
+ sb_service_->AddObserver(this); |
+ } |
} |
} // namespace safe_browsing |