1 // Copyright 2019 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 CHROMECAST_BROWSER_WEBVIEW_WEB_CONTENT_CONTROLLER_H_ 6 #define CHROMECAST_BROWSER_WEBVIEW_WEB_CONTENT_CONTROLLER_H_ 7 8 #include <deque> 9 #include <memory> 10 #include <set> 11 #include <string> 12 13 #include "chromecast/browser/webview/js_channel_service.h" 14 #include "chromecast/browser/webview/proto/webview.pb.h" 15 #include "components/exo/surface.h" 16 #include "components/exo/surface_observer.h" 17 #include "content/public/browser/render_widget_host.h" 18 #include "content/public/browser/web_contents_observer.h" 19 #include "ui/base/ime/input_method.h" 20 #include "ui/base/ime/input_method_observer.h" 21 #include "ui/events/gestures/gesture_recognizer_impl.h" 22 23 namespace aura { 24 class Window; 25 } // namespace aura 26 27 namespace content { 28 class RenderFrameHost; 29 } // namespace content 30 31 namespace chromecast { 32 33 class WebContentJsChannels; 34 35 // Processes proto commands to control WebContents 36 class WebContentController 37 : public exo::SurfaceObserver, 38 public content::WebContentsObserver, 39 public content::RenderWidgetHost::InputEventObserver, 40 public JsClientInstance::Observer { 41 public: 42 class Client { 43 public: ~Client()44 virtual ~Client() {} 45 virtual void EnqueueSend( 46 std::unique_ptr<webview::WebviewResponse> response) = 0; 47 virtual void OnError(const std::string& error_message) = 0; 48 }; 49 // Touch event information recorded so that acks can be sent in the same 50 // order. Stripped down from the normal event flow's TouchEventAckQueue. 51 struct TouchData { 52 uint32_t id; 53 content::RenderWidgetHostView* rwhv; 54 bool acked; 55 ui::EventResult result; 56 }; 57 58 explicit WebContentController(Client* client); 59 ~WebContentController() override; 60 61 virtual void Destroy() = 0; 62 63 virtual void ProcessRequest(const webview::WebviewRequest& request); 64 65 // Attach this web contents to an aura window as a child. 66 void AttachTo(aura::Window* window, int window_id); 67 68 // Invoked when the aura window becomes visible and is fully initialized. 69 void OnVisible(aura::Window* window); 70 client()71 Client* client() const { return client_; } 72 73 protected: 74 // content::WebContentsObserver 75 void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; 76 void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; 77 void RenderFrameHostChanged(content::RenderFrameHost* old_host, 78 content::RenderFrameHost* new_host) override; 79 void MainFrameWasResized(bool width_changed) override; 80 void FrameSizeChanged(content::RenderFrameHost* render_frame_host, 81 const gfx::Size& frame_size) override; 82 void RenderViewCreated(content::RenderViewHost* render_view_host) override; 83 void RenderViewDeleted(content::RenderViewHost* render_view_host) override; 84 85 static void RegisterRenderWidgetInputObserverFromRenderFrameHost( 86 WebContentController* web_content_controller, 87 content::RenderFrameHost* render_frame_host); 88 89 // Subclasses are expected to add/remove this as a WebContentsObserver on 90 // whatever WebContents this manages. 91 virtual content::WebContents* GetWebContents() = 0; 92 Client* client_; // Not owned. 93 bool has_navigation_delegate_ = false; 94 std::unique_ptr<WebContentJsChannels> js_channels_; 95 96 private: 97 void ProcessInputEvent(const webview::InputEvent& ev); 98 void RegisterRenderWidgetInputObserver( 99 content::RenderWidgetHost* render_widget_host); 100 void UnregisterRenderWidgetInputObserver( 101 content::RenderWidgetHost* render_widget_host); 102 void AckTouchEvent(content::RenderWidgetHostView* rhwv, 103 uint32_t unique_event_id, 104 ui::EventResult result); 105 void JavascriptCallback(int64_t id, base::Value result); 106 void HandleEvaluateJavascript( 107 int64_t id, 108 const webview::EvaluateJavascriptRequest& request); 109 void HandleAddJavascriptChannels( 110 const webview::AddJavascriptChannelsRequest& request); 111 void HandleRemoveJavascriptChannels( 112 const webview::RemoveJavascriptChannelsRequest& request); 113 void HandleGetCurrentUrl(int64_t id); 114 void HandleCanGoBack(int64_t id); 115 void HandleCanGoForward(int64_t id); 116 void HandleClearCache(); 117 void HandleClearCookies(int64_t id); 118 void HandleGetTitle(int64_t id); 119 void HandleResize(const gfx::Size& size); 120 viz::SurfaceId GetSurfaceId(); 121 void ChannelModified(content::RenderFrameHost* frame, 122 const std::string& channel, 123 bool added); 124 JsChannelCallback GetJsChannelCallback(); 125 void SendInitialChannelSet(JsClientInstance* instance); 126 127 // exo::SurfaceObserver 128 void OnSurfaceDestroying(exo::Surface* surface) override; 129 130 // JsClientInstance::Observer 131 void OnJsClientInstanceRegistered(int process_id, 132 int routing_id, 133 JsClientInstance* instance) override; 134 135 // content::RenderWidgetHost::InputEventObserver 136 void OnInputEventAck(blink::mojom::InputEventResultSource source, 137 blink::mojom::InputEventResultState state, 138 const blink::WebInputEvent&) override; 139 140 ui::GestureRecognizerImpl gesture_recognizer_; 141 std::deque<TouchData> touch_queue_; 142 143 exo::Surface* surface_ = nullptr; 144 145 std::set<std::string> current_javascript_channel_set_; 146 std::set<content::RenderFrameHost*> current_render_frame_set_; 147 std::set<content::RenderWidgetHost*> current_render_widget_set_; 148 149 // Observes the aura window and calls back to the controller for visibility 150 // events. 151 class WebviewWindowVisibilityObserver : public aura::WindowObserver { 152 public: 153 explicit WebviewWindowVisibilityObserver(aura::Window* window, 154 WebContentController* controller); 155 ~WebviewWindowVisibilityObserver() override; 156 157 WebviewWindowVisibilityObserver(const WebviewWindowVisibilityObserver&) = 158 delete; 159 WebviewWindowVisibilityObserver& operator=( 160 const WebviewWindowVisibilityObserver&) = delete; 161 162 private: 163 // aura::WindowObserver 164 void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; 165 void OnWindowDestroyed(aura::Window* window) override; 166 167 aura::Window* window_; 168 WebContentController* controller_; 169 }; 170 171 std::unique_ptr<WebviewWindowVisibilityObserver> window_visibility_observer_; 172 std::unique_ptr<ui::InputMethodObserver> input_method_observer_; 173 174 base::WeakPtrFactory<WebContentController> weak_ptr_factory_{this}; 175 176 DISALLOW_COPY_AND_ASSIGN(WebContentController); 177 }; 178 179 class WebContentJsChannels 180 : public base::SupportsWeakPtr<WebContentJsChannels> { 181 public: 182 explicit WebContentJsChannels(WebContentController::Client* client); 183 ~WebContentJsChannels(); 184 185 void SendMessage(const std::string& channel, const std::string& message); 186 187 private: 188 WebContentController::Client* client_; 189 190 DISALLOW_COPY_AND_ASSIGN(WebContentJsChannels); 191 }; 192 193 } // namespace chromecast 194 195 #endif // CHROMECAST_BROWSER_WEBVIEW_WEB_CONTENT_CONTROLLER_H_ 196