Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / supervised_user / supervised_user_navigation_observer.cc
blobfef9193a60e15e87d025304a51a028952b17762d
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/metrics/histogram.h"
10 #include "base/strings/string_util.h"
11 #include "chrome/browser/history/history_service_factory.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/supervised_user/supervised_user_interstitial.h"
15 #include "chrome/browser/supervised_user/supervised_user_resource_throttle.h"
16 #include "chrome/browser/supervised_user/supervised_user_service.h"
17 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
18 #include "chrome/browser/tab_contents/tab_util.h"
19 #include "chrome/grit/generated_resources.h"
20 #include "components/history/content/browser/history_context_helper.h"
21 #include "components/history/core/browser/history_service.h"
22 #include "components/history/core/browser/history_types.h"
23 #include "components/infobars/core/confirm_infobar_delegate.h"
24 #include "components/infobars/core/infobar.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/render_frame_host.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/user_metrics.h"
30 #include "ui/base/l10n/l10n_util.h"
32 #if !defined(OS_ANDROID)
33 #include "chrome/browser/ui/browser.h"
34 #include "chrome/browser/ui/browser_commands.h"
35 #include "chrome/browser/ui/browser_finder.h"
36 #include "chrome/browser/ui/browser_list.h"
37 #include "chrome/browser/ui/host_desktop.h"
38 #include "chrome/browser/ui/tabs/tab_strip_model.h"
39 #endif
41 using base::Time;
42 using content::NavigationEntry;
44 namespace {
47 // Helpers --------------------------------------------------------------------
49 #if !defined(OS_ANDROID)
50 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
51 // http://crbug.com/313377
52 void GoBackToSafety(content::WebContents* web_contents) {
53 // For now, just go back one page (the user didn't retreat from that page,
54 // so it should be okay).
55 content::NavigationController* controller =
56 &web_contents->GetController();
57 if (controller->CanGoBack()) {
58 controller->GoBack();
59 return;
62 // If we can't go back (because we opened a new tab), try to close the tab.
63 // If this is the last tab on this desktop, open a new window.
64 chrome::HostDesktopType host_desktop_type =
65 chrome::GetHostDesktopTypeForNativeView(web_contents->GetNativeView());
66 const BrowserList* browser_list = BrowserList::GetInstance(host_desktop_type);
67 if (browser_list->size() == 1) {
68 Browser* browser = browser_list->get(0);
69 DCHECK(browser == chrome::FindBrowserWithWebContents(web_contents));
70 if (browser->tab_strip_model()->count() == 1)
71 chrome::NewEmptyWindow(browser->profile(), browser->host_desktop_type());
74 web_contents->GetDelegate()->CloseContents(web_contents);
76 #endif
78 // SupervisedUserWarningInfoBarDelegate ---------------------------------------
80 class SupervisedUserWarningInfoBarDelegate : public ConfirmInfoBarDelegate {
81 public:
82 // Creates a supervised user warning infobar and delegate and adds the infobar
83 // to |infobar_service|. Returns the infobar if it was successfully added.
84 static infobars::InfoBar* Create(InfoBarService* infobar_service);
86 private:
87 SupervisedUserWarningInfoBarDelegate();
88 ~SupervisedUserWarningInfoBarDelegate() override;
90 // ConfirmInfoBarDelegate:
91 bool ShouldExpire(const NavigationDetails& details) const override;
92 void InfoBarDismissed() override;
93 base::string16 GetMessageText() const override;
94 int GetButtons() const override;
95 base::string16 GetButtonLabel(InfoBarButton button) const override;
96 bool Accept() override;
98 DISALLOW_COPY_AND_ASSIGN(SupervisedUserWarningInfoBarDelegate);
101 // static
102 infobars::InfoBar* SupervisedUserWarningInfoBarDelegate::Create(
103 InfoBarService* infobar_service) {
104 return infobar_service->AddInfoBar(
105 infobar_service->CreateConfirmInfoBar(scoped_ptr<ConfirmInfoBarDelegate>(
106 new SupervisedUserWarningInfoBarDelegate())));
109 SupervisedUserWarningInfoBarDelegate::SupervisedUserWarningInfoBarDelegate()
110 : ConfirmInfoBarDelegate() {
113 SupervisedUserWarningInfoBarDelegate::~SupervisedUserWarningInfoBarDelegate() {
116 bool SupervisedUserWarningInfoBarDelegate::ShouldExpire(
117 const NavigationDetails& details) const {
118 // SupervisedUserNavigationObserver removes us below.
119 return false;
122 void SupervisedUserWarningInfoBarDelegate::InfoBarDismissed() {
123 content::WebContents* web_contents =
124 InfoBarService::WebContentsFromInfoBar(infobar());
125 SupervisedUserNavigationObserver::FromWebContents(
126 web_contents)->WarnInfoBarDismissed();
129 base::string16 SupervisedUserWarningInfoBarDelegate::GetMessageText() const {
130 return l10n_util::GetStringUTF16(IDS_SUPERVISED_USER_WARN_INFOBAR_MESSAGE);
133 int SupervisedUserWarningInfoBarDelegate::GetButtons() const {
134 return BUTTON_OK;
137 base::string16 SupervisedUserWarningInfoBarDelegate::GetButtonLabel(
138 InfoBarButton button) const {
139 DCHECK_EQ(BUTTON_OK, button);
140 return l10n_util::GetStringUTF16(IDS_SUPERVISED_USER_WARN_INFOBAR_GO_BACK);
143 bool SupervisedUserWarningInfoBarDelegate::Accept() {
144 #if defined(OS_ANDROID)
145 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
146 // http://crbug.com/313377
147 NOTIMPLEMENTED();
148 #else
149 GoBackToSafety(InfoBarService::WebContentsFromInfoBar(infobar()));
150 #endif
152 return false;
156 } // namespace
158 // SupervisedUserNavigationObserver -------------------------------------------
160 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SupervisedUserNavigationObserver);
162 SupervisedUserNavigationObserver::~SupervisedUserNavigationObserver() {
165 SupervisedUserNavigationObserver::SupervisedUserNavigationObserver(
166 content::WebContents* web_contents)
167 : WebContentsObserver(web_contents),
168 warn_infobar_(NULL) {
169 Profile* profile =
170 Profile::FromBrowserContext(web_contents->GetBrowserContext());
171 supervised_user_service_ =
172 SupervisedUserServiceFactory::GetForProfile(profile);
173 url_filter_ = supervised_user_service_->GetURLFilterForUIThread();
176 void SupervisedUserNavigationObserver::WarnInfoBarDismissed() {
177 DCHECK(warn_infobar_);
178 warn_infobar_ = NULL;
181 void SupervisedUserNavigationObserver::DidCommitProvisionalLoadForFrame(
182 content::RenderFrameHost* render_frame_host,
183 const GURL& url,
184 ui::PageTransition transition_type) {
185 if (render_frame_host->GetParent())
186 return;
188 DVLOG(1) << "DidCommitProvisionalLoadForFrame " << url.spec();
189 SupervisedUserURLFilter::FilteringBehavior behavior =
190 url_filter_->GetFilteringBehaviorForURL(url);
192 if (behavior == SupervisedUserURLFilter::WARN && !warn_infobar_) {
193 warn_infobar_ = SupervisedUserWarningInfoBarDelegate::Create(
194 InfoBarService::FromWebContents(web_contents()));
195 } else if (behavior != SupervisedUserURLFilter::WARN && warn_infobar_) {
196 InfoBarService::FromWebContents(web_contents())->
197 RemoveInfoBar(warn_infobar_);
198 warn_infobar_ = NULL;
202 // static
203 void SupervisedUserNavigationObserver::OnRequestBlocked(
204 int render_process_host_id,
205 int render_view_id,
206 const GURL& url,
207 SupervisedUserURLFilter::FilteringBehaviorReason reason,
208 const base::Callback<void(bool)>& callback) {
209 content::WebContents* web_contents =
210 tab_util::GetWebContentsByID(render_process_host_id, render_view_id);
211 if (!web_contents) {
212 content::BrowserThread::PostTask(
213 content::BrowserThread::IO, FROM_HERE, base::Bind(callback, false));
214 return;
217 SupervisedUserNavigationObserver* navigation_observer =
218 SupervisedUserNavigationObserver::FromWebContents(web_contents);
219 if (navigation_observer)
220 navigation_observer->OnRequestBlockedInternal(url);
222 // Show the interstitial.
223 SupervisedUserInterstitial::Show(web_contents, url, reason, callback);
226 void SupervisedUserNavigationObserver::OnRequestBlockedInternal(
227 const GURL& url) {
228 Time timestamp = Time::Now(); // TODO(bauerb): Use SaneTime when available.
229 // Create a history entry for the attempt and mark it as such.
230 history::HistoryAddPageArgs add_page_args(
231 url, timestamp, history::ContextIDForWebContents(web_contents()), 0, url,
232 history::RedirectList(), ui::PAGE_TRANSITION_BLOCKED,
233 history::SOURCE_BROWSED, false);
235 // Add the entry to the history database.
236 Profile* profile =
237 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
238 history::HistoryService* history_service =
239 HistoryServiceFactory::GetForProfile(profile,
240 ServiceAccessType::IMPLICIT_ACCESS);
242 // |history_service| is null if saving history is disabled.
243 if (history_service)
244 history_service->AddPage(add_page_args);
246 scoped_ptr<NavigationEntry> entry(NavigationEntry::Create());
247 entry->SetVirtualURL(url);
248 entry->SetTimestamp(timestamp);
249 blocked_navigations_.push_back(entry.release());
250 SupervisedUserService* supervised_user_service =
251 SupervisedUserServiceFactory::GetForProfile(profile);
252 supervised_user_service->DidBlockNavigation(web_contents());