summaryrefslogtreecommitdiff
path: root/chromium/content/browser/frame_host/interstitial_page_impl.h
blob: d23262f505e896974b4f6be2bbece1eb07ff01f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
// Copyright 2013 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.

#ifndef CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_IMPL_H_
#define CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_IMPL_H_

#include <stdint.h>

#include <memory>

#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "build/build_config.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/navigator_delegate.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/renderer_preferences.h"
#include "url/gurl.h"

namespace content {
class NavigationControllerImpl;
class RenderViewHostImpl;
class RenderWidgetHostView;
class TextInputManager;
class WebContentsView;

namespace mojom {
class CreateNewWindowParams;
}

enum ResourceRequestAction {
  BLOCK,
  RESUME,
  CANCEL
};

class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
                                            public NotificationObserver,
                                            public RenderFrameHostDelegate,
                                            public RenderWidgetHostObserver,
                                            public RenderViewHostDelegate,
                                            public RenderWidgetHostDelegate,
                                            public NavigatorDelegate {
 public:
  // The different state of actions the user can take in an interstitial.
  enum ActionState {
    NO_ACTION,           // No action has been taken yet.
    PROCEED_ACTION,      // "Proceed" was selected.
    DONT_PROCEED_ACTION  // "Don't proceed" was selected.
  };

  InterstitialPageImpl(WebContents* web_contents,
                       RenderWidgetHostDelegate* render_widget_host_delegate,
                       bool new_navigation,
                       const GURL& url,
                       InterstitialPageDelegate* delegate);
  ~InterstitialPageImpl() override;

  // InterstitialPage implementation:
  void Show() override;
  void Hide() override;
  void DontProceed() override;
  void Proceed() override;
  WebContents* GetWebContents() const override;
  RenderFrameHost* GetMainFrame() const override;
  InterstitialPageDelegate* GetDelegateForTesting() override;
  void DontCreateViewForTesting() override;
  void SetSize(const gfx::Size& size) override;
  void Focus() override;

  // Allows the user to navigate away by disabling the interstitial, canceling
  // the pending request, and unblocking the hidden renderer.  The interstitial
  // will stay visible until the navigation completes.
  void CancelForNavigation();

  // Focus the first (last if reverse is true) element in the interstitial page.
  // Called when tab traversing.
  void FocusThroughTabTraversal(bool reverse);

  RenderWidgetHostView* GetView();

  bool pause_throbber() const { return pause_throbber_; }

  // TODO(nasko): This should move to InterstitialPageNavigatorImpl, but in
  // the meantime make it public, so it can be called directly.
  void DidNavigate(
      RenderViewHost* render_view_host,
      const FrameHostMsg_DidCommitProvisionalLoad_Params& params);

  // NavigatorDelegate implementation.
  WebContents* OpenURL(const OpenURLParams& params) override;
  const std::string& GetUserAgentOverride() const override;
  bool ShouldOverrideUserAgentInNewTabs() override;
  bool ShowingInterstitialPage() const override;

 protected:
  // NotificationObserver method:
  void Observe(int type,
               const NotificationSource& source,
               const NotificationDetails& details) override;

  // RenderFrameHostDelegate implementation:
  bool OnMessageReceived(RenderFrameHostImpl* render_frame_host,
                         const IPC::Message& message) override;
  void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
  void UpdateTitle(RenderFrameHost* render_frame_host,
                   const base::string16& title,
                   base::i18n::TextDirection title_direction) override;
  InterstitialPage* GetAsInterstitialPage() override;
  ui::AXMode GetAccessibilityMode() const override;
  void ExecuteEditCommand(const std::string& command,
                          const base::Optional<base::string16>& value) override;
  void Cut() override;
  void Copy() override;
  void Paste() override;
  void SelectAll() override;
  void CreateNewWindow(
      RenderFrameHost* opener,
      int32_t render_view_route_id,
      int32_t main_frame_route_id,
      int32_t main_frame_widget_route_id,
      const mojom::CreateNewWindowParams& params,
      SessionStorageNamespace* session_storage_namespace) override;
  void ShowCreatedWindow(int process_id,
                         int main_frame_widget_route_id,
                         WindowOpenDisposition disposition,
                         const gfx::Rect& initial_rect,
                         bool user_gesture) override;
  void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) override;
  Visibility GetVisibility() const override;

  // RenderViewHostDelegate implementation:
  RenderViewHostDelegateView* GetDelegateView() override;
  bool OnMessageReceived(RenderViewHostImpl* render_view_host,
                         const IPC::Message& message) override;
  const GURL& GetMainFrameLastCommittedURL() const override;
  void RenderViewTerminated(RenderViewHost* render_view_host,
                            base::TerminationStatus status,
                            int error_code) override;
  RendererPreferences GetRendererPrefs(
      BrowserContext* browser_context) const override;
  void CreateNewWidget(int32_t render_process_id,
                       int32_t route_id,
                       mojom::WidgetPtr widget,
                       blink::WebPopupType popup_type) override;
  void CreateNewFullscreenWidget(int32_t render_process_id,
                                 int32_t route_id,
                                 mojom::WidgetPtr widget) override;
  void ShowCreatedWidget(int process_id,
                         int route_id,
                         const gfx::Rect& initial_rect) override;
  void ShowCreatedFullscreenWidget(int process_id, int route_id) override;

  SessionStorageNamespace* GetSessionStorageNamespace(
      SiteInstance* instance) override;

  FrameTree* GetFrameTree() override;

  // RenderWidgetHostDelegate implementation:
  void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) override;
  KeyboardEventProcessingResult PreHandleKeyboardEvent(
      const NativeWebKeyboardEvent& event) override;
  void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
  TextInputManager* GetTextInputManager() override;
  RenderWidgetHostInputEventRouter* GetInputEventRouter() override;
  BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override;
  BrowserAccessibilityManager* GetOrCreateRootBrowserAccessibilityManager()
      override;

  bool enabled() const { return enabled_; }
  WebContents* web_contents() const;
  const GURL& url() const { return url_; }

  // Creates the WebContentsView that shows the interstitial RVH.
  // Overriden in unit tests.
  virtual WebContentsView* CreateWebContentsView();

  // Notification magic.
  NotificationRegistrar notification_registrar_;

 private:
  class InterstitialPageRVHDelegateView;
  class UnderlyingContentObserver : public WebContentsObserver {
   public:
    UnderlyingContentObserver(WebContents* web_contents,
                              InterstitialPageImpl* interstitial);

    // WebContentsObserver implementation:
    void WebContentsDestroyed() override;
    void NavigationEntryCommitted(
        const LoadCommittedDetails& load_details) override;

    // This observer does not override OnMessageReceived or otherwise handle
    // messages from the underlying content, because the interstitial should not
    // care about them. Messages from the interstitial page (which has its own
    // FrameTree) arrive through the RenderFrameHostDelegate interface, not
    // WebContentsObserver.

   private:
    InterstitialPageImpl* const interstitial_;

    DISALLOW_COPY_AND_ASSIGN(UnderlyingContentObserver);
  };

  // RenderWidgetHostObserver implementation:
  void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override;

  // Disable the interstitial:
  // - if it is not yet showing, then it won't be shown.
  // - any command sent by the RenderViewHost will be ignored.
  void Disable();

  // Delete ourselves, causing Shutdown on the RVH to be called.
  void Shutdown();

  void OnNavigatingAwayOrTabClosing();

  // Executes the passed action on the ResourceDispatcher (on the IO thread).
  // Used to block/resume/cancel requests for the RenderViewHost hidden by this
  // interstitial.
  void TakeActionOnResourceDispatcher(ResourceRequestAction action);

  // IPC message handlers.
  void OnDomOperationResponse(RenderFrameHostImpl* source,
                              const std::string& json_string);

  // Creates the RenderViewHost containing the interstitial content.
  RenderViewHostImpl* CreateRenderViewHost();

  // Watches the underlying WebContents for reasons to cancel the interstitial.
  UnderlyingContentObserver underlying_content_observer_;

  // The contents in which we are displayed.  This is valid until Hide is
  // called, at which point it will be set to NULL because the WebContents
  // itself may be deleted.
  WebContents* web_contents_;

  // The NavigationController for the content this page is being displayed over.
  NavigationControllerImpl* controller_;

  // Delegate for dispatching keyboard events and accessing the native view.
  RenderWidgetHostDelegate* render_widget_host_delegate_;

  // The URL that is shown when the interstitial is showing.
  GURL url_;

  // Whether this interstitial is shown as a result of a new navigation (in
  // which case a transient navigation entry is created).
  bool new_navigation_;

  // Whether we should discard the pending navigation entry when not proceeding.
  // This is to deal with cases where |new_navigation_| is true but a new
  // pending entry was created since this interstitial was shown and we should
  // not discard it.
  bool should_discard_pending_nav_entry_;

  // Whether this interstitial is enabled.  See Disable() for more info.
  bool enabled_;

  // Whether the Proceed or DontProceed methods have been called yet.
  ActionState action_taken_;

  // The RenderViewHost displaying the interstitial contents.  This is valid
  // until Hide is called, at which point it will be set to NULL, signifying
  // that shutdown has started.
  // TODO(creis): This is now owned by the FrameTree.  We should route things
  // through the tree's root RenderFrameHost instead.
  RenderViewHostImpl* render_view_host_;

  // The frame tree structure of the current page.
  std::unique_ptr<FrameTree> frame_tree_;

  // The IDs for the Render[View|Process]Host hidden by this interstitial.
  int original_child_id_;
  int original_rvh_id_;

  // Whether or not we should change the title of the contents when hidden (to
  // revert it to its original value).
  bool should_revert_web_contents_title_;

  // Whether the ResourceDispatcherHost has been notified to cancel/resume the
  // resource requests blocked for the RenderViewHost.
  bool resource_dispatcher_host_notified_;

  // The original title of the contents that should be reverted to when the
  // interstitial is hidden.
  base::string16 original_web_contents_title_;

  // Our RenderViewHostDelegateView, necessary for accelerators to work.
  std::unique_ptr<InterstitialPageRVHDelegateView> rvh_delegate_view_;

  // Settings passed to the renderer.
  mutable RendererPreferences renderer_preferences_;

  bool create_view_;

  // Whether the throbber should be paused. This is true from the moment the
  // interstitial is shown until the moment the interstitial goes away or the
  // user chooses to proceed.
  bool pause_throbber_;

  std::unique_ptr<InterstitialPageDelegate> delegate_;

  scoped_refptr<SessionStorageNamespace> session_storage_namespace_;

  ScopedObserver<RenderWidgetHost, RenderWidgetHostObserver> widget_observer_;

  base::WeakPtrFactory<InterstitialPageImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(InterstitialPageImpl);
};

}  // namespace content

#endif  // CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_IMPL_H_