| // Copyright 2014 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/supervised_user/supervised_user_navigation_observer.h" |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "chrome/browser/history/history_service_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/supervised_user/supervised_user_interstitial.h" |
| #include "chrome/browser/supervised_user/supervised_user_service.h" |
| #include "chrome/browser/supervised_user/supervised_user_service_factory.h" |
| #include "chrome/browser/tab_contents/tab_util.h" |
| #include "components/history/content/browser/history_context_helper.h" |
| #include "components/history/core/browser/history_service.h" |
| #include "components/history/core/browser/history_types.h" |
| #include "components/sessions/content/content_serialized_navigation_builder.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/navigation_entry.h" |
| |
| using base::Time; |
| using content::NavigationEntry; |
| |
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(SupervisedUserNavigationObserver); |
| |
| SupervisedUserNavigationObserver::~SupervisedUserNavigationObserver() { |
| supervised_user_service_->RemoveObserver(this); |
| } |
| |
| SupervisedUserNavigationObserver::SupervisedUserNavigationObserver( |
| content::WebContents* web_contents) |
| : web_contents_(web_contents), weak_ptr_factory_(this) { |
| Profile* profile = |
| Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
| supervised_user_service_ = |
| SupervisedUserServiceFactory::GetForProfile(profile); |
| url_filter_ = supervised_user_service_->GetURLFilterForUIThread(); |
| supervised_user_service_->AddObserver(this); |
| } |
| |
| // static |
| void SupervisedUserNavigationObserver::OnRequestBlocked( |
| const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, |
| const GURL& url, |
| SupervisedUserURLFilter::FilteringBehaviorReason reason, |
| const base::Callback<void(bool)>& callback) { |
| content::WebContents* web_contents = web_contents_getter.Run(); |
| if (!web_contents) { |
| content::BrowserThread::PostTask( |
| content::BrowserThread::IO, FROM_HERE, base::Bind(callback, false)); |
| return; |
| } |
| |
| SupervisedUserNavigationObserver* navigation_observer = |
| SupervisedUserNavigationObserver::FromWebContents(web_contents); |
| if (navigation_observer) |
| navigation_observer->OnRequestBlockedInternal(url); |
| |
| // Show the interstitial. |
| SupervisedUserInterstitial::Show(web_contents, url, reason, callback); |
| } |
| |
| void SupervisedUserNavigationObserver::OnRequestBlockedInternal( |
| const GURL& url) { |
| Time timestamp = Time::Now(); // TODO(bauerb): Use SaneTime when available. |
| // Create a history entry for the attempt and mark it as such. |
| history::HistoryAddPageArgs add_page_args( |
| url, timestamp, history::ContextIDForWebContents(web_contents_), 0, url, |
| history::RedirectList(), ui::PAGE_TRANSITION_BLOCKED, |
| history::SOURCE_BROWSED, false); |
| |
| // Add the entry to the history database. |
| Profile* profile = |
| Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
| history::HistoryService* history_service = |
| HistoryServiceFactory::GetForProfile(profile, |
| ServiceAccessType::IMPLICIT_ACCESS); |
| |
| // |history_service| is null if saving history is disabled. |
| if (history_service) |
| history_service->AddPage(add_page_args); |
| |
| scoped_ptr<NavigationEntry> entry(NavigationEntry::Create()); |
| entry->SetVirtualURL(url); |
| entry->SetTimestamp(timestamp); |
| scoped_ptr<sessions::SerializedNavigationEntry> serialized_entry( |
| new sessions::SerializedNavigationEntry()); |
| *serialized_entry = |
| sessions::ContentSerializedNavigationBuilder::FromNavigationEntry( |
| blocked_navigations_.size(), *entry); |
| blocked_navigations_.push_back(serialized_entry.release()); |
| supervised_user_service_->DidBlockNavigation(web_contents_); |
| } |
| |
| void SupervisedUserNavigationObserver::OnURLFilterChanged() { |
| url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( |
| web_contents_->GetLastCommittedURL(), |
| base::Bind(&SupervisedUserNavigationObserver::URLFilterCheckCallback, |
| weak_ptr_factory_.GetWeakPtr(), |
| web_contents_->GetLastCommittedURL())); |
| } |
| |
| void SupervisedUserNavigationObserver::URLFilterCheckCallback( |
| const GURL& url, |
| SupervisedUserURLFilter::FilteringBehavior behavior, |
| SupervisedUserURLFilter::FilteringBehaviorReason reason, |
| bool uncertain) { |
| // If the page has been changed in the meantime, we can exit. |
| if (url != web_contents_->GetLastCommittedURL()) |
| return; |
| |
| if (behavior == SupervisedUserURLFilter::FilteringBehavior::BLOCK) { |
| SupervisedUserInterstitial::Show(web_contents_, url, reason, |
| base::Callback<void(bool)>()); |
| } |
| } |