| Index: chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc
|
| diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..30ffaa0f0bb3691fa6655f00df804cd86d1b954a
|
| --- /dev/null
|
| +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc
|
| @@ -0,0 +1,216 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer.h"
|
| +
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/time/time.h"
|
| +#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h"
|
| +#include "chrome/browser/sessions/session_tab_helper.h"
|
| +#include "content/public/browser/navigation_handle.h"
|
| +#include "content/public/browser/render_frame_host.h"
|
| +#include "content/public/browser/resource_request_details.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/resource_type.h"
|
| +
|
| +using content::WebContents;
|
| +
|
| +namespace {
|
| +const char kWebContentsUserDataKey[] =
|
| + "web_contents_safe_browsing_navigation_observer";
|
| +} // namespace
|
| +
|
| +namespace safe_browsing {
|
| +
|
| +// SafeBrowsingNavigationObserver::NavigationEvent-----------------------------
|
| +NavigationEvent::NavigationEvent()
|
| + : source_url(),
|
| + source_tab_id(-1),
|
| + target_url(),
|
| + target_tab_id(-1),
|
| + frame_id(-1),
|
| + main_frame_url(),
|
| + timestamp(base::Time::Now()),
|
| + is_user_initiated(false),
|
| + has_committed(false),
|
| + has_server_redirect(false),
|
| + server_redirect_url() {}
|
| +
|
| +NavigationEvent::NavigationEvent(NavigationEvent&& nav_event)
|
| + : source_url(std::move(nav_event.source_url)),
|
| + source_tab_id(std::move(nav_event.source_tab_id)),
|
| + target_url(std::move(nav_event.target_url)),
|
| + target_tab_id(std::move(nav_event.target_tab_id)),
|
| + frame_id(nav_event.frame_id),
|
| + main_frame_url(std::move(nav_event.main_frame_url)),
|
| + timestamp(nav_event.timestamp),
|
| + is_user_initiated(nav_event.is_user_initiated),
|
| + has_committed(nav_event.has_committed),
|
| + has_server_redirect(nav_event.has_server_redirect),
|
| + server_redirect_url(std::move(nav_event.server_redirect_url)) {}
|
| +
|
| +NavigationEvent& NavigationEvent::operator=(NavigationEvent&& nav_event) {
|
| + source_url = std::move(nav_event.source_url);
|
| + source_tab_id = std::move(nav_event.source_tab_id);
|
| + target_url = std::move(nav_event.target_url);
|
| + target_tab_id = std::move(nav_event.target_tab_id);
|
| + frame_id = nav_event.frame_id;
|
| + main_frame_url = std::move(nav_event.main_frame_url);
|
| + timestamp = nav_event.timestamp;
|
| + is_user_initiated = nav_event.is_user_initiated;
|
| + has_committed = nav_event.has_committed;
|
| + has_server_redirect = nav_event.has_server_redirect;
|
| + server_redirect_url = std::move(nav_event.server_redirect_url);
|
| + return *this;
|
| +}
|
| +
|
| +NavigationEvent::~NavigationEvent() {}
|
| +
|
| +// SafeBrowsingNavigationObserver --------------------------------------------
|
| +
|
| +// static
|
| +void SafeBrowsingNavigationObserver::MaybeCreateForWebContents(
|
| + content::WebContents* web_contents) {
|
| + if (FromWebContents(web_contents))
|
| + return;
|
| + NOTIMPLEMENTED();
|
| + // TODO(jialiul): This method will be called by TabHelpers::AttachTabHelpers.
|
| + // Complete this method when the entire class is ready.
|
| +}
|
| +
|
| +// static
|
| +SafeBrowsingNavigationObserver* SafeBrowsingNavigationObserver::FromWebContents(
|
| + content::WebContents* web_contents) {
|
| + return static_cast<SafeBrowsingNavigationObserver*>(
|
| + web_contents->GetUserData(kWebContentsUserDataKey));
|
| +}
|
| +
|
| +SafeBrowsingNavigationObserver::SafeBrowsingNavigationObserver(
|
| + content::WebContents* contents,
|
| + const scoped_refptr<SafeBrowsingNavigationObserverManager>& manager)
|
| + : content::WebContentsObserver(contents),
|
| + manager_(manager),
|
| + has_user_gesture_(false),
|
| + last_user_gesture_timestamp_(base::Time::Now()) {}
|
| +
|
| +SafeBrowsingNavigationObserver::~SafeBrowsingNavigationObserver() {}
|
| +
|
| +// Called when a navigation started in the WebContents. |navigation_handle| in
|
| +// paramter is unique to this navigation, which will appear in the following
|
| +// DidRedirectNavigation, and DidFinishNavigation too.
|
| +void SafeBrowsingNavigationObserver::DidStartNavigation(
|
| + content::NavigationHandle* navigation_handle) {
|
| + // If we already seen this navigation_handle before, no need to do anything.
|
| + if (navigation_handle_map_.find(navigation_handle) !=
|
| + navigation_handle_map_.end())
|
| + return;
|
| +
|
| + // Construct a NavigationEvent based on available information in
|
| + // navigation_handle.
|
| + NavigationEvent nav_event;
|
| + content::RenderFrameHost* host =
|
| + navigation_handle->GetWebContents()->FindFrameByFrameTreeNodeId(
|
| + navigation_handle->GetFrameTreeNodeId());
|
| +
|
| + // If there was URL previously committed in this render frame host,
|
| + // set it as the source url of this navigation. Otherwise, this is the
|
| + // first url going to commit in this frame. We set navigation_handle's URL as
|
| + // the source url.
|
| + if (host && host->GetLastCommittedURL().is_valid()) {
|
| + nav_event.source_url = SafeBrowsingNavigationObserverManager::ClearURLRef(
|
| + host->GetLastCommittedURL());
|
| + } else {
|
| + nav_event.source_url = SafeBrowsingNavigationObserverManager::ClearURLRef(
|
| + navigation_handle->GetURL());
|
| + }
|
| + nav_event.target_url = SafeBrowsingNavigationObserverManager::ClearURLRef(
|
| + navigation_handle->GetURL());
|
| +
|
| + nav_event.source_tab_id =
|
| + SessionTabHelper::IdForTab(navigation_handle->GetWebContents());
|
| + nav_event.timestamp = base::Time::Now();
|
| + nav_event.frame_id = navigation_handle->GetFrameTreeNodeId();
|
| +
|
| + if (navigation_handle->IsInMainFrame()) {
|
| + nav_event.main_frame_url = nav_event.source_url;
|
| + } else {
|
| + nav_event.main_frame_url =
|
| + SafeBrowsingNavigationObserverManager::ClearURLRef(
|
| + navigation_handle->GetWebContents()->GetLastCommittedURL());
|
| + }
|
| + if (has_user_gesture_ &&
|
| + !SafeBrowsingNavigationObserverManager::IsUserGestureExpired(
|
| + last_user_gesture_timestamp_)) {
|
| + nav_event.is_user_initiated = has_user_gesture_;
|
| + manager_->OnUserGestureConsumed(web_contents(),
|
| + last_user_gesture_timestamp_);
|
| + }
|
| + has_user_gesture_ = false;
|
| + navigation_handle_map_.insert(
|
| + std::make_pair(navigation_handle, std::move(nav_event)));
|
| +}
|
| +
|
| +void SafeBrowsingNavigationObserver::DidRedirectNavigation(
|
| + content::NavigationHandle* navigation_handle) {
|
| + // We should have already seen this navigation_handle in DidStartNavigation.
|
| + if (navigation_handle_map_.find(navigation_handle) ==
|
| + navigation_handle_map_.end())
|
| + return;
|
| +
|
| + NavigationEvent* nav_event = &navigation_handle_map_[navigation_handle];
|
| + nav_event->has_server_redirect = true;
|
| + nav_event->server_redirect_url =
|
| + SafeBrowsingNavigationObserverManager::ClearURLRef(
|
| + navigation_handle->GetURL());
|
| + nav_event->timestamp = base::Time::Now();
|
| +}
|
| +
|
| +void SafeBrowsingNavigationObserver::DidFinishNavigation(
|
| + content::NavigationHandle* navigation_handle) {
|
| + if (navigation_handle_map_.find(navigation_handle) ==
|
| + navigation_handle_map_.end())
|
| + return;
|
| +
|
| + // If it is an error page, we ignore this navigation.
|
| + if (navigation_handle->IsErrorPage()) {
|
| + navigation_handle_map_.erase(navigation_handle);
|
| + return;
|
| + }
|
| + NavigationEvent* nav_event = &navigation_handle_map_[navigation_handle];
|
| +
|
| + // Set is_user_initiated to has_user_gesture || browser_initiated.
|
| + nav_event->is_user_initiated =
|
| + nav_event->is_user_initiated || !navigation_handle->IsRendererInitiated();
|
| + nav_event->has_committed = navigation_handle->HasCommitted();
|
| + nav_event->target_tab_id =
|
| + SessionTabHelper::IdForTab(navigation_handle->GetWebContents());
|
| + nav_event->timestamp = base::Time::Now();
|
| +
|
| + GURL nav_event_key =
|
| + navigation_handle->HasCommitted()
|
| + ? SafeBrowsingNavigationObserverManager::ClearURLRef(
|
| + navigation_handle->GetRenderFrameHost()->GetLastCommittedURL())
|
| + : nav_event->has_server_redirect ? nav_event->server_redirect_url
|
| + : nav_event->target_url;
|
| + manager_->RecordNavigationEvent(nav_event_key, nav_event);
|
| + navigation_handle_map_.erase(navigation_handle);
|
| +}
|
| +
|
| +void SafeBrowsingNavigationObserver::DidGetUserInteraction(
|
| + const blink::WebInputEvent::Type type) {
|
| + last_user_gesture_timestamp_ = base::Time::Now();
|
| + has_user_gesture_ = true;
|
| + // TODO (jialiul): Refine user gesture logic when DidOpenRequestedURL
|
| + // covers all retargetting cases.
|
| + manager_->RecordUserGestureForWebContents(web_contents(),
|
| + last_user_gesture_timestamp_);
|
| +}
|
| +
|
| +void SafeBrowsingNavigationObserver::WebContentsDestroyed() {
|
| + manager_->OnWebContentDestroyed(web_contents());
|
| + web_contents()->RemoveUserData(kWebContentsUserDataKey);
|
| + // web_contents is null after this function.
|
| +}
|
| +
|
| +} // namespace safe_browsing
|
|
|