1 // Copyright (c) 2012 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/managed_mode/managed_mode_navigation_observer.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.h"
12 #include "chrome/browser/history/history_service_factory.h"
13 #include "chrome/browser/history/history_types.h"
14 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
15 #include "chrome/browser/infobars/infobar_service.h"
16 #include "chrome/browser/managed_mode/managed_mode_interstitial.h"
17 #include "chrome/browser/managed_mode/managed_mode_resource_throttle.h"
18 #include "chrome/browser/managed_mode/managed_mode_url_filter.h"
19 #include "chrome/browser/managed_mode/managed_user_service.h"
20 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/tab_contents/tab_util.h"
23 #include "components/infobars/core/infobar.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/navigation_entry.h"
26 #include "content/public/browser/render_process_host.h"
27 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/user_metrics.h"
29 #include "grit/generated_resources.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"
42 using content::NavigationEntry
;
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()) {
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
);
78 // ManagedModeWarningInfoBarDelegate ------------------------------------------
80 class ManagedModeWarningInfoBarDelegate
: public ConfirmInfoBarDelegate
{
82 // Creates a managed mode warning infobar and delegate and adds the infobar to
83 // |infobar_service|. Returns the infobar if it was successfully added.
84 static infobars::InfoBar
* Create(InfoBarService
* infobar_service
);
87 ManagedModeWarningInfoBarDelegate();
88 virtual ~ManagedModeWarningInfoBarDelegate();
90 // ConfirmInfoBarDelegate:
91 virtual bool ShouldExpire(const NavigationDetails
& details
) const OVERRIDE
;
92 virtual void InfoBarDismissed() OVERRIDE
;
93 virtual base::string16
GetMessageText() const OVERRIDE
;
94 virtual int GetButtons() const OVERRIDE
;
95 virtual base::string16
GetButtonLabel(InfoBarButton button
) const OVERRIDE
;
96 virtual bool Accept() OVERRIDE
;
98 DISALLOW_COPY_AND_ASSIGN(ManagedModeWarningInfoBarDelegate
);
102 infobars::InfoBar
* ManagedModeWarningInfoBarDelegate::Create(
103 InfoBarService
* infobar_service
) {
104 return infobar_service
->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
105 scoped_ptr
<ConfirmInfoBarDelegate
>(
106 new ManagedModeWarningInfoBarDelegate())));
109 ManagedModeWarningInfoBarDelegate::ManagedModeWarningInfoBarDelegate()
110 : ConfirmInfoBarDelegate() {
113 ManagedModeWarningInfoBarDelegate::~ManagedModeWarningInfoBarDelegate() {
116 bool ManagedModeWarningInfoBarDelegate::ShouldExpire(
117 const NavigationDetails
& details
) const {
118 // ManagedModeNavigationObserver removes us below.
122 void ManagedModeWarningInfoBarDelegate::InfoBarDismissed() {
123 content::WebContents
* web_contents
=
124 InfoBarService::WebContentsFromInfoBar(infobar());
125 ManagedModeNavigationObserver::FromWebContents(
126 web_contents
)->WarnInfoBarDismissed();
129 base::string16
ManagedModeWarningInfoBarDelegate::GetMessageText() const {
130 return l10n_util::GetStringUTF16(IDS_MANAGED_USER_WARN_INFOBAR_MESSAGE
);
133 int ManagedModeWarningInfoBarDelegate::GetButtons() const {
137 base::string16
ManagedModeWarningInfoBarDelegate::GetButtonLabel(
138 InfoBarButton button
) const {
139 DCHECK_EQ(BUTTON_OK
, button
);
140 return l10n_util::GetStringUTF16(IDS_MANAGED_USER_WARN_INFOBAR_GO_BACK
);
143 bool ManagedModeWarningInfoBarDelegate::Accept() {
144 #if defined(OS_ANDROID)
145 // TODO(bauerb): Get rid of the platform-specific #ifdef here.
146 // http://crbug.com/313377
149 GoBackToSafety(InfoBarService::WebContentsFromInfoBar(infobar()));
158 // ManagedModeNavigationObserver ----------------------------------------------
160 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ManagedModeNavigationObserver
);
162 ManagedModeNavigationObserver::~ManagedModeNavigationObserver() {
165 ManagedModeNavigationObserver::ManagedModeNavigationObserver(
166 content::WebContents
* web_contents
)
167 : WebContentsObserver(web_contents
),
168 warn_infobar_(NULL
) {
170 Profile::FromBrowserContext(web_contents
->GetBrowserContext());
171 managed_user_service_
= ManagedUserServiceFactory::GetForProfile(profile
);
172 url_filter_
= managed_user_service_
->GetURLFilterForUIThread();
175 void ManagedModeNavigationObserver::WarnInfoBarDismissed() {
176 DCHECK(warn_infobar_
);
177 warn_infobar_
= NULL
;
180 void ManagedModeNavigationObserver::ProvisionalChangeToMainFrameUrl(
182 content::RenderFrameHost
* render_frame_host
) {
183 ManagedModeURLFilter::FilteringBehavior behavior
=
184 url_filter_
->GetFilteringBehaviorForURL(url
);
186 if (behavior
== ManagedModeURLFilter::WARN
|| !warn_infobar_
)
189 // If we shouldn't have a warn infobar remove it here.
190 InfoBarService::FromWebContents(web_contents())->RemoveInfoBar(warn_infobar_
);
191 warn_infobar_
= NULL
;
194 void ManagedModeNavigationObserver::DidCommitProvisionalLoadForFrame(
196 const base::string16
& frame_unique_name
,
199 content::PageTransition transition_type
,
200 content::RenderViewHost
* render_view_host
) {
204 DVLOG(1) << "DidCommitProvisionalLoadForFrame " << url
.spec();
205 ManagedModeURLFilter::FilteringBehavior behavior
=
206 url_filter_
->GetFilteringBehaviorForURL(url
);
208 if (behavior
== ManagedModeURLFilter::WARN
&& !warn_infobar_
) {
209 warn_infobar_
= ManagedModeWarningInfoBarDelegate::Create(
210 InfoBarService::FromWebContents(web_contents()));
215 void ManagedModeNavigationObserver::OnRequestBlocked(
216 int render_process_host_id
,
219 const base::Callback
<void(bool)>& callback
) {
220 content::WebContents
* web_contents
=
221 tab_util::GetWebContentsByID(render_process_host_id
, render_view_id
);
223 content::BrowserThread::PostTask(
224 content::BrowserThread::IO
, FROM_HERE
, base::Bind(callback
, false));
228 ManagedModeNavigationObserver
* navigation_observer
=
229 ManagedModeNavigationObserver::FromWebContents(web_contents
);
230 if (navigation_observer
)
231 navigation_observer
->OnRequestBlockedInternal(url
);
233 // Show the interstitial.
234 ManagedModeInterstitial::Show(web_contents
, url
, callback
);
237 void ManagedModeNavigationObserver::OnRequestBlockedInternal(const GURL
& url
) {
238 Time timestamp
= Time::Now(); // TODO(bauerb): Use SaneTime when available.
239 // Create a history entry for the attempt and mark it as such.
240 history::HistoryAddPageArgs
add_page_args(
241 url
, timestamp
, web_contents(), 0,
242 url
, history::RedirectList(),
243 content::PAGE_TRANSITION_BLOCKED
, history::SOURCE_BROWSED
,
246 // Add the entry to the history database.
248 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
249 HistoryService
* history_service
=
250 HistoryServiceFactory::GetForProfile(profile
, Profile::IMPLICIT_ACCESS
);
252 // |history_service| is null if saving history is disabled.
254 history_service
->AddPage(add_page_args
);
256 scoped_ptr
<NavigationEntry
> entry(NavigationEntry::Create());
257 entry
->SetVirtualURL(url
);
258 entry
->SetTimestamp(timestamp
);
259 blocked_navigations_
.push_back(entry
.release());
260 ManagedUserService
* managed_user_service
=
261 ManagedUserServiceFactory::GetForProfile(profile
);
262 managed_user_service
->DidBlockNavigation(web_contents());