Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / managed_mode / managed_mode_navigation_observer.cc
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.
4
5 #include "chrome/browser/managed_mode/managed_mode_navigation_observer.h"
6
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.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"
31
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
40
41 using base::Time;
42 using content::NavigationEntry;
43
44 namespace {
45
46
47 // Helpers --------------------------------------------------------------------
48
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;
60   }
61
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());
72   }
73
74   web_contents->GetDelegate()->CloseContents(web_contents);
75 }
76 #endif
77
78 // ManagedModeWarningInfoBarDelegate ------------------------------------------
79
80 class ManagedModeWarningInfoBarDelegate : public ConfirmInfoBarDelegate {
81  public:
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);
85
86  private:
87   ManagedModeWarningInfoBarDelegate();
88   virtual ~ManagedModeWarningInfoBarDelegate();
89
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;
97
98   DISALLOW_COPY_AND_ASSIGN(ManagedModeWarningInfoBarDelegate);
99 };
100
101 // static
102 infobars::InfoBar* ManagedModeWarningInfoBarDelegate::Create(
103     InfoBarService* infobar_service) {
104   return infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
105       scoped_ptr<ConfirmInfoBarDelegate>(
106           new ManagedModeWarningInfoBarDelegate())));
107 }
108
109 ManagedModeWarningInfoBarDelegate::ManagedModeWarningInfoBarDelegate()
110     : ConfirmInfoBarDelegate() {
111 }
112
113 ManagedModeWarningInfoBarDelegate::~ManagedModeWarningInfoBarDelegate() {
114 }
115
116 bool ManagedModeWarningInfoBarDelegate::ShouldExpire(
117     const NavigationDetails& details) const {
118   // ManagedModeNavigationObserver removes us below.
119   return false;
120 }
121
122 void ManagedModeWarningInfoBarDelegate::InfoBarDismissed() {
123   content::WebContents* web_contents =
124       InfoBarService::WebContentsFromInfoBar(infobar());
125   ManagedModeNavigationObserver::FromWebContents(
126       web_contents)->WarnInfoBarDismissed();
127 }
128
129 base::string16 ManagedModeWarningInfoBarDelegate::GetMessageText() const {
130   return l10n_util::GetStringUTF16(IDS_MANAGED_USER_WARN_INFOBAR_MESSAGE);
131 }
132
133 int ManagedModeWarningInfoBarDelegate::GetButtons() const {
134   return BUTTON_OK;
135 }
136
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);
141 }
142
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
147   NOTIMPLEMENTED();
148 #else
149   GoBackToSafety(InfoBarService::WebContentsFromInfoBar(infobar()));
150 #endif
151
152   return false;
153 }
154
155
156 }  // namespace
157
158 // ManagedModeNavigationObserver ----------------------------------------------
159
160 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ManagedModeNavigationObserver);
161
162 ManagedModeNavigationObserver::~ManagedModeNavigationObserver() {
163 }
164
165 ManagedModeNavigationObserver::ManagedModeNavigationObserver(
166     content::WebContents* web_contents)
167     : WebContentsObserver(web_contents),
168       warn_infobar_(NULL) {
169   Profile* profile =
170       Profile::FromBrowserContext(web_contents->GetBrowserContext());
171   managed_user_service_ = ManagedUserServiceFactory::GetForProfile(profile);
172   url_filter_ = managed_user_service_->GetURLFilterForUIThread();
173 }
174
175 void ManagedModeNavigationObserver::WarnInfoBarDismissed() {
176   DCHECK(warn_infobar_);
177   warn_infobar_ = NULL;
178 }
179
180 void ManagedModeNavigationObserver::ProvisionalChangeToMainFrameUrl(
181     const GURL& url,
182     content::RenderFrameHost* render_frame_host) {
183   ManagedModeURLFilter::FilteringBehavior behavior =
184       url_filter_->GetFilteringBehaviorForURL(url);
185
186   if (behavior == ManagedModeURLFilter::WARN || !warn_infobar_)
187     return;
188
189   // If we shouldn't have a warn infobar remove it here.
190   InfoBarService::FromWebContents(web_contents())->RemoveInfoBar(warn_infobar_);
191   warn_infobar_ = NULL;
192 }
193
194 void ManagedModeNavigationObserver::DidCommitProvisionalLoadForFrame(
195     int64 frame_id,
196     const base::string16& frame_unique_name,
197     bool is_main_frame,
198     const GURL& url,
199     content::PageTransition transition_type,
200     content::RenderViewHost* render_view_host) {
201   if (!is_main_frame)
202     return;
203
204   DVLOG(1) << "DidCommitProvisionalLoadForFrame " << url.spec();
205   ManagedModeURLFilter::FilteringBehavior behavior =
206       url_filter_->GetFilteringBehaviorForURL(url);
207
208   if (behavior == ManagedModeURLFilter::WARN && !warn_infobar_) {
209     warn_infobar_ = ManagedModeWarningInfoBarDelegate::Create(
210         InfoBarService::FromWebContents(web_contents()));
211   }
212 }
213
214 // static
215 void ManagedModeNavigationObserver::OnRequestBlocked(
216     int render_process_host_id,
217     int render_view_id,
218     const GURL& url,
219     const base::Callback<void(bool)>& callback) {
220   content::WebContents* web_contents =
221       tab_util::GetWebContentsByID(render_process_host_id, render_view_id);
222   if (!web_contents) {
223     content::BrowserThread::PostTask(
224         content::BrowserThread::IO, FROM_HERE, base::Bind(callback, false));
225     return;
226   }
227
228   ManagedModeNavigationObserver* navigation_observer =
229       ManagedModeNavigationObserver::FromWebContents(web_contents);
230   if (navigation_observer)
231     navigation_observer->OnRequestBlockedInternal(url);
232
233   // Show the interstitial.
234   ManagedModeInterstitial::Show(web_contents, url, callback);
235 }
236
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,
244         false);
245
246   // Add the entry to the history database.
247   Profile* profile =
248       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
249   HistoryService* history_service =
250      HistoryServiceFactory::GetForProfile(profile, Profile::IMPLICIT_ACCESS);
251
252   // |history_service| is null if saving history is disabled.
253   if (history_service)
254     history_service->AddPage(add_page_args);
255
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());
263 }