1 // Copyright 2018 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 #ifndef FUCHSIA_ENGINE_BROWSER_FRAME_IMPL_H_
6 #define FUCHSIA_ENGINE_BROWSER_FRAME_IMPL_H_
7 
8 #include <fuchsia/web/cpp/fidl.h>
9 #include <lib/fidl/cpp/binding_set.h>
10 #include <lib/ui/scenic/cpp/view_ref_pair.h>
11 #include <lib/zx/channel.h>
12 
13 #include <list>
14 #include <map>
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19 
20 #include "base/macros.h"
21 #include "base/memory/read_only_shared_memory_region.h"
22 #include "base/optional.h"
23 #include "components/media_control/browser/media_blocker.h"
24 #include "components/on_load_script_injector/browser/on_load_script_injector_host.h"
25 #include "content/public/browser/web_contents_delegate.h"
26 #include "content/public/browser/web_contents_observer.h"
27 #include "fuchsia/engine/browser/accessibility_bridge.h"
28 #include "fuchsia/engine/browser/event_filter.h"
29 #include "fuchsia/engine/browser/frame_permission_controller.h"
30 #include "fuchsia/engine/browser/navigation_controller_impl.h"
31 #include "fuchsia/engine/browser/theme_manager.h"
32 #include "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
33 #include "ui/aura/window_tree_host.h"
34 #include "ui/wm/core/focus_controller.h"
35 #include "url/gurl.h"
36 
37 namespace content {
38 class FromRenderFrameHost;
39 }  // namespace content
40 
41 class CastStreamingSessionClient;
42 class ContextImpl;
43 class FrameWindowTreeHost;
44 class FrameLayoutManager;
45 class MediaPlayerImpl;
46 class NavigationPolicyHandler;
47 
48 // Implementation of fuchsia.web.Frame based on content::WebContents.
49 class FrameImpl : public fuchsia::web::Frame,
50                   public content::WebContentsObserver,
51                   public content::WebContentsDelegate {
52  public:
53   // Returns FrameImpl that owns the |web_contents| or nullptr if the
54   // |web_contents| is nullptr.
55   static FrameImpl* FromWebContents(content::WebContents* web_contents);
56 
57   // Returns FrameImpl that owns the |render_frame_host| or nullptr if the
58   // |render_frame_host| is nullptr.
59   static FrameImpl* FromRenderFrameHost(
60       content::RenderFrameHost* render_frame_host);
61 
62   // |params_for_popups| is saved and applied to popups created by content
63   // running in this Frame.
64   FrameImpl(std::unique_ptr<content::WebContents> web_contents,
65             ContextImpl* context,
66             fuchsia::web::CreateFrameParams params_for_popups,
67             fidl::InterfaceRequest<fuchsia::web::Frame> frame_request);
68   ~FrameImpl() override;
69 
70   FrameImpl(const FrameImpl&) = delete;
71   FrameImpl& operator=(const FrameImpl&) = delete;
72 
media_session_id()73   uint64_t media_session_id() const { return media_session_id_; }
74 
permission_controller()75   FramePermissionController* permission_controller() {
76     return &permission_controller_;
77   }
78 
url_request_rewrite_rules_manager()79   UrlRequestRewriteRulesManager* url_request_rewrite_rules_manager() {
80     return &url_request_rewrite_rules_manager_;
81   }
82 
navigation_policy_handler()83   NavigationPolicyHandler* navigation_policy_handler() {
84     return navigation_policy_handler_.get();
85   }
86 
87   zx::unowned_channel GetBindingChannelForTest() const;
web_contents_for_test()88   content::WebContents* web_contents_for_test() const {
89     return web_contents_.get();
90   }
has_view_for_test()91   bool has_view_for_test() const { return window_tree_host_ != nullptr; }
accessibility_bridge_for_test()92   AccessibilityBridge* accessibility_bridge_for_test() const {
93     return accessibility_bridge_.get();
94   }
set_semantics_manager_for_test(fuchsia::accessibility::semantics::SemanticsManager * semantics_manager)95   void set_semantics_manager_for_test(
96       fuchsia::accessibility::semantics::SemanticsManager* semantics_manager) {
97     semantics_manager_for_test_ = semantics_manager;
98   }
cast_streaming_session_client_for_test()99   CastStreamingSessionClient* cast_streaming_session_client_for_test() {
100     return cast_streaming_session_client_.get();
101   }
102 
103   // Enables explicit sites filtering and set the error page. If |error_page| is
104   // empty, the default error page will be used.
105   void EnableExplicitSitesFilter(std::string error_page);
106 
explicit_sites_filter_error_page()107   const base::Optional<std::string>& explicit_sites_filter_error_page() const {
108     return explicit_sites_filter_error_page_;
109   }
110 
111  private:
112   FRIEND_TEST_ALL_PREFIXES(FrameImplTest, DelayedNavigationEventAck);
113   FRIEND_TEST_ALL_PREFIXES(FrameImplTest, NavigationObserverDisconnected);
114   FRIEND_TEST_ALL_PREFIXES(FrameImplTest, NoNavigationObserverAttached);
115   FRIEND_TEST_ALL_PREFIXES(FrameImplTest, ReloadFrame);
116   FRIEND_TEST_ALL_PREFIXES(FrameImplTest, Stop);
117 
118   aura::Window* root_window() const;
119 
120   // Shared implementation for the ExecuteJavaScript[NoResult]() APIs.
121   void ExecuteJavaScriptInternal(std::vector<std::string> origins,
122                                  fuchsia::mem::Buffer script,
123                                  ExecuteJavaScriptCallback callback,
124                                  bool need_result);
125 
126   // Sends the next entry in |pending_popups_| to |popup_listener_|.
127   void MaybeSendPopup();
128 
129   void OnPopupListenerDisconnected(zx_status_t status);
130 
131   // Cleans up the MediaPlayerImpl on disconnect.
132   void OnMediaPlayerDisconnect();
133 
134   // An error handler for |accessibility_bridge_|.
135   void OnAccessibilityError(zx_status_t error);
136 
137   // Initializes WindowTreeHost for the view with the specified |view_token|.
138   // |view_token| may be uninitialized in headless mode.
139   void InitWindowTreeHost(fuchsia::ui::views::ViewToken view_token,
140                           scenic::ViewRefPair view_ref_pair);
141 
142   // Destroys the WindowTreeHost along with its view or other associated
143   // resources.
144   void DestroyWindowTreeHost();
145 
146   // Destroys |this| and sends the FIDL |error| to the client.
147   void CloseAndDestroyFrame(zx_status_t error);
148 
149   // Determines whether |message| is a Cast Streaming message and if so, handles
150   // it. Returns whether it handled the message, regardless of whether that was
151   // successful. If true is returned, |callback| has been called. Returns false
152   // immediately if Cast Streaming support is not enabled. Called by
153   // PostMessage().
154   bool MaybeHandleCastStreamingMessage(std::string* origin,
155                                        fuchsia::web::WebMessage* message,
156                                        PostMessageCallback* callback);
157 
158   void MaybeStartCastStreaming(content::NavigationHandle* navigation_handle);
159 
160   // fuchsia::web::Frame implementation.
161   void CreateView(fuchsia::ui::views::ViewToken view_token) override;
162   void CreateViewWithViewRef(fuchsia::ui::views::ViewToken view_token,
163                              fuchsia::ui::views::ViewRefControl control_ref,
164                              fuchsia::ui::views::ViewRef view_ref) override;
165   void GetMediaPlayer(fidl::InterfaceRequest<fuchsia::media::sessions2::Player>
166                           player) override;
167   void GetNavigationController(
168       fidl::InterfaceRequest<fuchsia::web::NavigationController> controller)
169       override;
170   void ExecuteJavaScript(std::vector<std::string> origins,
171                          fuchsia::mem::Buffer script,
172                          ExecuteJavaScriptCallback callback) override;
173   void ExecuteJavaScriptNoResult(
174       std::vector<std::string> origins,
175       fuchsia::mem::Buffer script,
176       ExecuteJavaScriptNoResultCallback callback) override;
177   void AddBeforeLoadJavaScript(
178       uint64_t id,
179       std::vector<std::string> origins,
180       fuchsia::mem::Buffer script,
181       AddBeforeLoadJavaScriptCallback callback) override;
182   void RemoveBeforeLoadJavaScript(uint64_t id) override;
183   void PostMessage(std::string origin,
184                    fuchsia::web::WebMessage message,
185                    fuchsia::web::Frame::PostMessageCallback callback) override;
186   void SetNavigationEventListener(
187       fidl::InterfaceHandle<fuchsia::web::NavigationEventListener> listener)
188       override;
189   void SetJavaScriptLogLevel(fuchsia::web::ConsoleLogLevel level) override;
190   void ConfigureInputTypes(fuchsia::web::InputTypes types,
191                            fuchsia::web::AllowInputState allow) override;
192   void SetPopupFrameCreationListener(
193       fidl::InterfaceHandle<fuchsia::web::PopupFrameCreationListener> listener)
194       override;
195   void SetUrlRequestRewriteRules(
196       std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
197       SetUrlRequestRewriteRulesCallback callback) override;
198   void EnableHeadlessRendering() override;
199   void DisableHeadlessRendering() override;
200   void SetMediaSessionId(uint64_t session_id) override;
201   void ForceContentDimensions(
202       std::unique_ptr<fuchsia::ui::gfx::vec2> web_dips) override;
203   void SetPermissionState(fuchsia::web::PermissionDescriptor permission,
204                           std::string web_origin,
205                           fuchsia::web::PermissionState state) override;
206   void SetBlockMediaLoading(bool blocked) override;
207   void MediaStartedPlaying(const MediaPlayerInfo& video_type,
208                            const content::MediaPlayerId& id) override;
209   void MediaStoppedPlaying(
210       const MediaPlayerInfo& video_type,
211       const content::MediaPlayerId& id,
212       WebContentsObserver::MediaStoppedReason reason) override;
213   void GetPrivateMemorySize(GetPrivateMemorySizeCallback callback) override;
214   void SetNavigationPolicyProvider(
215       fuchsia::web::NavigationPolicyProviderParams params,
216       fidl::InterfaceHandle<fuchsia::web::NavigationPolicyProvider> provider)
217       override;
218   void SetPreferredTheme(fuchsia::settings::ThemeType theme) override;
219 
220   // content::WebContentsDelegate implementation.
221   void CloseContents(content::WebContents* source) override;
222   bool DidAddMessageToConsole(content::WebContents* source,
223                               blink::mojom::ConsoleMessageLevel log_level,
224                               const base::string16& message,
225                               int32_t line_no,
226                               const base::string16& source_id) override;
227   bool IsWebContentsCreationOverridden(
228       content::SiteInstance* source_site_instance,
229       content::mojom::WindowContainerType window_container_type,
230       const GURL& opener_url,
231       const std::string& frame_name,
232       const GURL& target_url) override;
233   void WebContentsCreated(content::WebContents* source_contents,
234                           int opener_render_process_id,
235                           int opener_render_frame_id,
236                           const std::string& frame_name,
237                           const GURL& target_url,
238                           content::WebContents* new_contents) override;
239   void AddNewContents(content::WebContents* source,
240                       std::unique_ptr<content::WebContents> new_contents,
241                       const GURL& target_url,
242                       WindowOpenDisposition disposition,
243                       const gfx::Rect& initial_rect,
244                       bool user_gesture,
245                       bool* was_blocked) override;
246   void RequestMediaAccessPermission(
247       content::WebContents* web_contents,
248       const content::MediaStreamRequest& request,
249       content::MediaResponseCallback callback) override;
250   bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host,
251                                   const GURL& security_origin,
252                                   blink::mojom::MediaStreamType type) override;
253 
254   // content::WebContentsObserver implementation.
255   void ReadyToCommitNavigation(
256       content::NavigationHandle* navigation_handle) override;
257   void DidFinishLoad(content::RenderFrameHost* render_frame_host,
258                      const GURL& validated_url) override;
259   void RenderViewCreated(content::RenderViewHost* render_view_host) override;
260   void RenderViewReady() override;
261   void DidFirstVisuallyNonEmptyPaint() override;
262   void ResourceLoadComplete(
263       content::RenderFrameHost* render_frame_host,
264       const content::GlobalRequestID& request_id,
265       const blink::mojom::ResourceLoadInfo& resource_load_info) override;
266 
267   const std::unique_ptr<content::WebContents> web_contents_;
268   ContextImpl* const context_;
269 
270   // Parameters applied to popups created by content running in this Frame.
271   const fuchsia::web::CreateFrameParams params_for_popups_;
272 
273   std::unique_ptr<FrameWindowTreeHost> window_tree_host_;
274 
275   std::unique_ptr<wm::FocusController> focus_controller_;
276 
277   // Owned via |window_tree_host_|.
278   FrameLayoutManager* layout_manager_ = nullptr;
279 
280   std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
281   fuchsia::accessibility::semantics::SemanticsManager*
282       semantics_manager_for_test_ = nullptr;
283 
284   EventFilter event_filter_;
285   NavigationControllerImpl navigation_controller_;
286   logging::LogSeverity log_level_;
287   UrlRequestRewriteRulesManager url_request_rewrite_rules_manager_;
288   FramePermissionController permission_controller_;
289   std::unique_ptr<NavigationPolicyHandler> navigation_policy_handler_;
290 
291   // Session ID to use for fuchsia.media.AudioConsumer. Set with
292   // SetMediaSessionId().
293   uint64_t media_session_id_ = 0;
294 
295   // Used for receiving and dispatching popup created by this Frame.
296   fuchsia::web::PopupFrameCreationListenerPtr popup_listener_;
297   std::list<std::unique_ptr<content::WebContents>> pending_popups_;
298   bool popup_ack_outstanding_ = false;
299   gfx::Size render_size_override_;
300 
301   std::unique_ptr<MediaPlayerImpl> media_player_;
302   std::unique_ptr<CastStreamingSessionClient> cast_streaming_session_client_;
303   on_load_script_injector::OnLoadScriptInjectorHost<uint64_t> script_injector_;
304 
305   fidl::Binding<fuchsia::web::Frame> binding_;
306   media_control::MediaBlocker media_blocker_;
307 
308   ThemeManager theme_manager_;
309 
310   // The error page to be displayed when a navigation to an explicit site is
311   // filtered. Explicit sites are filtered if it has a value. If set to the
312   // empty string, the default error page will be displayed.
313   base::Optional<std::string> explicit_sites_filter_error_page_;
314 
315   base::WeakPtrFactory<FrameImpl> weak_factory_{this};
316 };
317 
318 #endif  // FUCHSIA_ENGINE_BROWSER_FRAME_IMPL_H_
319