1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PAGE_POPUP_IMPL_H_
32 #define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PAGE_POPUP_IMPL_H_
33 
34 #include "base/macros.h"
35 #include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
36 #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
37 #include "third_party/blink/public/web/web_page_popup.h"
38 #include "third_party/blink/renderer/core/core_export.h"
39 #include "third_party/blink/renderer/core/page/page_popup.h"
40 #include "third_party/blink/renderer/core/page/page_widget_delegate.h"
41 #include "third_party/blink/renderer/platform/heap/persistent.h"
42 #include "third_party/blink/renderer/platform/widget/widget_base_client.h"
43 #include "third_party/blink/renderer/platform/wtf/casting.h"
44 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
45 
46 namespace cc {
47 class Layer;
48 }
49 
50 namespace blink {
51 class Element;
52 class Page;
53 class PagePopupChromeClient;
54 class PagePopupClient;
55 class WebViewImpl;
56 class LocalDOMWindow;
57 class WidgetBase;
58 
59 class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
60                                            public PageWidgetEventHandler,
61                                            public PagePopup,
62                                            public RefCounted<WebPagePopupImpl>,
63                                            public WidgetBaseClient {
64   USING_FAST_MALLOC(WebPagePopupImpl);
65 
66  public:
67   ~WebPagePopupImpl() override;
68 
69   void Initialize(WebViewImpl*, PagePopupClient*);
70 
71   // Cancel informs the PopupClient that it should initiate shutdown of this
72   // popup via ClosePopup(). It is called to indicate the popup was closed due
73   // to a user gesture outside the popup or other such reasons, where a default
74   // cancelled response can be made.
75   //
76   // When the user chooses a value in the popup and thus it is closed, or if the
77   // origin in the DOM disppears, then the Cancel() step would be skipped and go
78   // directly to ClosePopup().
79   void Cancel();
80   // Once ClosePopup() has been called, the WebPagePopupImpl should be disowned
81   // by any clients, and will be reaped when then browser closes its
82   // RenderWidget which closes this object. This will call back to the
83   // PopupClient to say DidClosePopup(), and to the WebViewImpl to cleanup
84   // its reference to the popup.
85   //
86   // Only HasSamePopupClient() may still be called after ClosePopup() runs.
87   void ClosePopup();
88 
89   // Returns whether another WebPagePopupImpl has the same PopupClient as this
90   // instance. May be called after ClosePopup() has run still, in order to
91   // determine if a popup sharing the same client was created immediately after
92   // closing one.
HasSamePopupClient(WebPagePopupImpl * other)93   bool HasSamePopupClient(WebPagePopupImpl* other) {
94     return other && popup_client_ == other->popup_client_;
95   }
96 
WidgetClient()97   WebWidgetClient* WidgetClient() const { return web_page_popup_client_; }
98 
99   LocalDOMWindow* Window();
100 
101   // WebWidget implementation.
102   WebInputEventResult DispatchBufferedTouchEvents() override;
103   void SetCompositorVisible(bool visible) override;
104   void UpdateVisualState() override;
105   void WillBeginCompositorFrame() override;
106 
107   // WebPagePopup implementation.
108   gfx::Point PositionRelativeToOwner() override;
109   WebDocument GetDocument() override;
110   WebPagePopupClient* GetClientForTesting() const override;
111 
112   // PagePopup implementation.
113   void PostMessageToPopup(const String& message) override;
114 
115   // PageWidgetEventHandler implementation.
116   WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) override;
117 
118  private:
119   // WidgetBaseClient overrides:
120   void DispatchRafAlignedInput(base::TimeTicks frame_time) override;
121   void BeginMainFrame(base::TimeTicks last_frame_time) override;
122   void RecordTimeToFirstActivePaint(base::TimeDelta duration) override;
123   void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
124 
125   // WebWidget implementation.
126   // NOTE: The WebWidget may still be used after requesting the popup to be
127   // closed and destroyed. But the Page and the MainFrame are destroyed
128   // immediately. So all methods (outside of initialization) that are part
129   // of the WebWidget need to check if close has already been initiated (they
130   // can do so by checking |page_|) and not crash! https://crbug.com/906340
131   void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*) override;
132   void BeginFrame(base::TimeTicks last_frame_time) override;
133   void UpdateLifecycle(WebLifecycleUpdate requested_update,
134                        DocumentUpdateReason reason) override;
135   void Resize(const WebSize&) override;
136   void Close() override;
137   WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
138   void SetFocus(bool) override;
139   WebURL GetURLForDebugTrace() override;
HitTestResultAt(const gfx::Point &)140   WebHitTestResult HitTestResultAt(const gfx::Point&) override { return {}; }
141 
142   // PageWidgetEventHandler functions
143   WebInputEventResult HandleCharEvent(const WebKeyboardEvent&) override;
144   WebInputEventResult HandleGestureEvent(const WebGestureEvent&) override;
145   void HandleMouseDown(LocalFrame& main_frame, const WebMouseEvent&) override;
146   WebInputEventResult HandleMouseWheel(LocalFrame& main_frame,
147                                        const WebMouseWheelEvent&) override;
148 
149   // This may only be called if page_ is non-null.
150   LocalFrame& MainFrame() const;
151 
152   Element* FocusedElement() const;
153 
154   bool IsViewportPointInWindow(int x, int y);
155 
156   // PagePopup function
157   AXObject* RootAXObject() override;
158   void SetWindowRect(const IntRect&) override;
159 
160   WebPagePopupImpl(
161       WebPagePopupClient*,
162       CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
163           widget_host,
164       CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
165           widget);
166   void DestroyPage();
167   void SetRootLayer(scoped_refptr<cc::Layer>);
168 
169   WebRect WindowRectInScreen() const;
170 
171   WebPagePopupClient* web_page_popup_client_;
172   WebViewImpl* web_view_;
173   // WebPagePopupImpl wraps its own Page that renders the content in the popup.
174   // This member is non-null between the call to Initialize() and the call to
175   // ClosePopup(). If page_ is non-null, it is guaranteed to have an attached
176   // main LocalFrame with a corresponding non-null LocalFrameView and non-null
177   // Document.
178   Persistent<Page> page_;
179   Persistent<PagePopupChromeClient> chrome_client_;
180   PagePopupClient* popup_client_;
181   bool closing_ = false;
182 
183   scoped_refptr<cc::Layer> root_layer_;
184   base::TimeTicks raf_aligned_input_start_time_;
185 
186   bool suppress_next_keypress_event_ = false;
187 
188   // Base functionality all widgets have. This is a member as to avoid
189   // complicated inheritance structures.
190   std::unique_ptr<WidgetBase> widget_base_;
191 
192   friend class WebPagePopup;
193   friend class PagePopupChromeClient;
194 
195   DISALLOW_COPY_AND_ASSIGN(WebPagePopupImpl);
196 };
197 
198 // WebPagePopupImpl is the only implementation of WebPagePopup and PagePopup, so
199 // no further checking required.
200 template <>
201 struct DowncastTraits<WebPagePopupImpl> {
202   static bool AllowFrom(const WebPagePopup& widget) { return true; }
203   static bool AllowFrom(const PagePopup& popup) { return true; }
204 };
205 
206 }  // namespace blink
207 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_PAGE_POPUP_IMPL_H_
208