1 // Copyright 2013 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 IOS_WEB_PUBLIC_WEB_STATE_H_
6 #define IOS_WEB_PUBLIC_WEB_STATE_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <utility>
14 #include <vector>
15 
16 #include "base/callback_forward.h"
17 #include "base/callback_list.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/strings/string_piece.h"
20 #include "base/supports_user_data.h"
21 #include "ios/web/public/deprecated/url_verification_constants.h"
22 #include "ios/web/public/navigation/referrer.h"
23 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
24 #include "mojo/public/cpp/system/message_pipe.h"
25 #include "ui/base/page_transition_types.h"
26 #include "ui/base/window_open_disposition.h"
27 #include "url/gurl.h"
28 
29 class GURL;
30 
31 @class CRWJSInjectionReceiver;
32 @class CRWSessionStorage;
33 @protocol CRWScrollableContent;
34 @protocol CRWWebViewProxy;
35 typedef id<CRWWebViewProxy> CRWWebViewProxyType;
36 @class UIView;
37 typedef UIView<CRWScrollableContent> CRWContentView;
38 
39 namespace base {
40 class DictionaryValue;
41 class Value;
42 }
43 
44 namespace gfx {
45 class Image;
46 class RectF;
47 }
48 
49 namespace web {
50 
51 class BrowserState;
52 class NavigationManager;
53 class SessionCertificatePolicyCache;
54 class WebFrame;
55 class WebFramesManager;
56 class WebInterstitial;
57 class WebStateDelegate;
58 class WebStateObserver;
59 class WebStatePolicyDecider;
60 
61 // Core interface for interaction with the web.
62 class WebState : public base::SupportsUserData {
63  public:
64   // Parameters for the Create() method.
65   struct CreateParams {
66     explicit CreateParams(web::BrowserState* browser_state);
67     ~CreateParams();
68 
69     // The corresponding BrowserState for the new WebState.
70     web::BrowserState* browser_state;
71 
72     // Whether the WebState is created as the result of a window.open or by
73     // clicking a link with a blank target.  Used to determine whether the
74     // WebState is allowed to be closed via window.close().
75     bool created_with_opener;
76   };
77 
78   // Parameters for the OpenURL() method.
79   struct OpenURLParams {
80     OpenURLParams(const GURL& url,
81                   const GURL& virtual_url,
82                   const Referrer& referrer,
83                   WindowOpenDisposition disposition,
84                   ui::PageTransition transition,
85                   bool is_renderer_initiated);
86     OpenURLParams(const GURL& url,
87                   const Referrer& referrer,
88                   WindowOpenDisposition disposition,
89                   ui::PageTransition transition,
90                   bool is_renderer_initiated);
91     OpenURLParams(const OpenURLParams& params);
92     ~OpenURLParams();
93 
94     // The URL/virtualURL/referrer to be opened.
95     GURL url;
96     GURL virtual_url;
97     Referrer referrer;
98 
99     // The disposition requested by the navigation source.
100     WindowOpenDisposition disposition;
101 
102     // The transition type of navigation.
103     ui::PageTransition transition;
104 
105     // Whether this navigation is initiated by the renderer process.
106     bool is_renderer_initiated;
107   };
108 
109   // InterfaceBinder can be instantiated by subclasses of WebState and returned
110   // by GetInterfaceBinderForMainFrame().
111   class InterfaceBinder {
112    public:
113     explicit InterfaceBinder(WebState* web_state);
114     ~InterfaceBinder();
115 
116     template <typename Interface>
AddInterface(base::RepeatingCallback<void (mojo::PendingReceiver<Interface>)> callback)117     void AddInterface(
118         base::RepeatingCallback<void(mojo::PendingReceiver<Interface>)>
119             callback) {
120       AddInterface(
121           Interface::Name_,
122           base::BindRepeating(&WrapCallback<Interface>, std::move(callback)));
123     }
124 
125     // Adds a callback to bind an interface receiver pipe carried by a
126     // GenericPendingReceiver.
127     using Callback =
128         base::RepeatingCallback<void(mojo::GenericPendingReceiver*)>;
129     void AddInterface(base::StringPiece interface_name, Callback callback);
130 
131     // Attempts to bind |receiver| by matching its interface name against the
132     // callbacks registered on this InterfaceBinder.
133     void BindInterface(mojo::GenericPendingReceiver receiver);
134 
135    private:
136     template <typename Interface>
WrapCallback(base::RepeatingCallback<void (mojo::PendingReceiver<Interface>)> callback,mojo::GenericPendingReceiver * receiver)137     static void WrapCallback(
138         base::RepeatingCallback<void(mojo::PendingReceiver<Interface>)>
139             callback,
140         mojo::GenericPendingReceiver* receiver) {
141       if (auto typed_receiver = receiver->As<Interface>())
142         callback.Run(std::move(typed_receiver));
143     }
144 
145     WebState* const web_state_;
146     std::map<std::string, Callback> callbacks_;
147 
148     DISALLOW_COPY_AND_ASSIGN(InterfaceBinder);
149   };
150 
151   // Creates a new WebState.
152   static std::unique_ptr<WebState> Create(const CreateParams& params);
153 
154   // Creates a new WebState from a serialized representation of the session.
155   // |session_storage| must not be nil.
156   static std::unique_ptr<WebState> CreateWithStorageSession(
157       const CreateParams& params,
158       CRWSessionStorage* session_storage);
159 
~WebState()160   ~WebState() override {}
161 
162   // A callback that returns a pointer to a WebState. The callback can always be
163   // used, but it may return nullptr if the info used to instantiate the
164   // callback can no longer be used to return a WebState.
165   using Getter = base::RepeatingCallback<WebState*(void)>;
166   // Use this variant for instances that will only run the callback a single
167   // time.
168   using OnceGetter = base::OnceCallback<WebState*(void)>;
169 
170   // Creates default WebState getters that return this WebState, or nullptr if
171   // the WebState has been deallocated.
172   virtual Getter CreateDefaultGetter() = 0;
173   virtual OnceGetter CreateDefaultOnceGetter() = 0;
174 
175   // Gets/Sets the delegate.
176   virtual WebStateDelegate* GetDelegate() = 0;
177   virtual void SetDelegate(WebStateDelegate* delegate) = 0;
178 
179   // Whether or not a web view is allowed to exist in this WebState. Defaults
180   // to false; this should be enabled before attempting to access the view.
181   virtual bool IsWebUsageEnabled() const = 0;
182   virtual void SetWebUsageEnabled(bool enabled) = 0;
183 
184   // The view containing the contents of the current web page. If the view has
185   // been purged due to low memory, this will recreate it. It is up to the
186   // caller to size the view.
187   virtual UIView* GetView() = 0;
188 
189   // Notifies the WebState that the WebContent is covered. Triggers
190   // visibilitychange event.
191   virtual void DidCoverWebContent() = 0;
192   // Notifies the WebState that the WebContent is no longer covered. Triggers
193   // visibilitychange event.
194   virtual void DidRevealWebContent() = 0;
195 
196   // Must be called when the WebState becomes shown/hidden.
197   virtual void WasShown() = 0;
198   virtual void WasHidden() = 0;
199 
200   // When |true|, attempt to prevent the WebProcess from suspending. Embedder
201   // must override WebClient::GetWindowedContainer to maintain this
202   // functionality.
203   virtual void SetKeepRenderProcessAlive(bool keep_alive) = 0;
204 
205   // Gets the BrowserState associated with this WebState. Can never return null.
206   virtual BrowserState* GetBrowserState() const = 0;
207 
208   // Opens a URL with the given disposition.  The transition specifies how this
209   // navigation should be recorded in the history system (for example, typed).
210   virtual void OpenURL(const OpenURLParams& params) = 0;
211 
212   // Stops any pending navigation.
213   virtual void Stop() = 0;
214 
215   // Gets the NavigationManager associated with this WebState. Can never return
216   // null.
217   virtual const NavigationManager* GetNavigationManager() const = 0;
218   virtual NavigationManager* GetNavigationManager() = 0;
219 
220   // Gets the WebFramesManager associated with this WebState. Can never return
221   // null.
222   virtual const WebFramesManager* GetWebFramesManager() const = 0;
223   virtual WebFramesManager* GetWebFramesManager() = 0;
224 
225   // Gets the SessionCertificatePolicyCache for this WebState.  Can never return
226   // null.
227   virtual const SessionCertificatePolicyCache*
228   GetSessionCertificatePolicyCache() const = 0;
229   virtual SessionCertificatePolicyCache* GetSessionCertificatePolicyCache() = 0;
230 
231   // Creates a serializable representation of the session. The returned value
232   // is autoreleased.
233   virtual CRWSessionStorage* BuildSessionStorage() = 0;
234 
235   // Gets the CRWJSInjectionReceiver associated with this WebState.
236   virtual CRWJSInjectionReceiver* GetJSInjectionReceiver() const = 0;
237 
238   // Loads |data| of type |mime_type| and replaces last committed URL with the
239   // given |url|.
240   virtual void LoadData(NSData* data, NSString* mime_type, const GURL& url) = 0;
241 
242   // DISCOURAGED. Prefer using |WebFrame CallJavaScriptFunction| instead because
243   // it restricts JavaScript execution to functions within __gCrWeb and can also
244   // call those functions on any frame in the page. ExecuteJavaScript here can
245   // execute arbitrary JavaScript code, which is not as safe and is restricted
246   // to executing only on the main frame.
247   // Runs JavaScript in the main frame's context. If a callback is provided, it
248   // will be used to return the result, when the result is available or script
249   // execution has failed due to an error.
250   // NOTE: Integer values will be returned as Type::DOUBLE because of underlying
251   // library limitation.
252   typedef base::OnceCallback<void(const base::Value*)> JavaScriptResultCallback;
253   virtual void ExecuteJavaScript(const base::string16& javascript) = 0;
254   virtual void ExecuteJavaScript(const base::string16& javascript,
255                                  JavaScriptResultCallback callback) = 0;
256 
257   // Asynchronously executes |javaScript| in the main frame's context,
258   // registering user interaction.
259   virtual void ExecuteUserJavaScript(NSString* javaScript) = 0;
260 
261   // Gets the contents MIME type.
262   virtual const std::string& GetContentsMimeType() const = 0;
263 
264   // Returns true if the current page is a web view with HTML.
265   virtual bool ContentIsHTML() const = 0;
266 
267   // Returns the current navigation title. This could be the title of the page
268   // if it is available or the URL.
269   virtual const base::string16& GetTitle() const = 0;
270 
271   // Returns true if the current page is loading.
272   virtual bool IsLoading() const = 0;
273 
274   // The fraction of the page load that has completed as a number between 0.0
275   // (nothing loaded) and 1.0 (fully loaded).
276   virtual double GetLoadingProgress() const = 0;
277 
278   // Whether the WebState is visible. Returns true after WasShown() call and
279   // false after WasHidden() call.
280   virtual bool IsVisible() const = 0;
281 
282   // Returns true if the web process backing this WebState is believed to
283   // currently be crashed.
284   virtual bool IsCrashed() const = 0;
285 
286   // Returns true if the web process backing this WebState is believed to
287   // currently be crashed or was evicted (by calling SetWebUsageEnabled
288   // with false).
289   // TODO(crbug.com/619971): Remove once all code has been ported to use
290   // IsCrashed() instead of IsEvicted().
291   virtual bool IsEvicted() const = 0;
292 
293   // Whether this instance is in the process of being destroyed.
294   virtual bool IsBeingDestroyed() const = 0;
295 
296   // Gets the URL currently being displayed in the URL bar, if there is one.
297   // This URL might be a pending navigation that hasn't committed yet, so it is
298   // not guaranteed to match the current page in this WebState. A typical
299   // example of this is interstitials, which show the URL of the new/loading
300   // page (active) but the security context is of the old page (last committed).
301   virtual const GURL& GetVisibleURL() const = 0;
302 
303   // Gets the last committed URL. It represents the current page that is
304   // displayed in this WebState. It represents the current security context.
305   virtual const GURL& GetLastCommittedURL() const = 0;
306 
307   // Returns the WebState view of the current URL. Moreover, this method
308   // will set the trustLevel enum to the appropriate level from a security point
309   // of view. The caller has to handle the case where |trust_level| is not
310   // appropriate.  Passing |null| will skip the trust check.
311   // TODO(crbug.com/457679): Figure out a clean API for this.
312   virtual GURL GetCurrentURL(URLVerificationTrustLevel* trust_level) const = 0;
313 
314   // Returns true if a WebInterstitial is currently displayed.
315   virtual bool IsShowingWebInterstitial() const = 0;
316 
317   // Returns the currently visible WebInterstitial if one is shown.
318   virtual WebInterstitial* GetWebInterstitial() const = 0;
319 
320   // Callback used to handle script commands. |message| is the JS message sent
321   // from the |sender_frame| in the page, |page_url| is the URL of page's main
322   // frame, |user_is_interacting| indicates if the user is interacting with the
323   // page.
324   // TODO(crbug.com/881813): remove |page_url|.
325   using ScriptCommandCallbackSignature =
326       void(const base::DictionaryValue& message,
327            const GURL& page_url,
328            bool user_is_interacting,
329            web::WebFrame* sender_frame);
330   using ScriptCommandCallback =
331       base::RepeatingCallback<ScriptCommandCallbackSignature>;
332   using ScriptCommandSubscription =
333       base::RepeatingCallbackList<ScriptCommandCallbackSignature>::Subscription;
334   // Registers |callback| for JS message whose 'command' matches
335   // |command_prefix|. The returned ScriptCommandSubscription should be stored
336   // by the caller. When the description object is destroyed, it will unregister
337   // |callback| if this WebState is still alive, and do nothing if this WebState
338   // is already destroyed. Therefore if the caller want to stop receiving JS
339   // messages it can just destroy the subscription object.
340   virtual std::unique_ptr<ScriptCommandSubscription> AddScriptCommandCallback(
341       const ScriptCommandCallback& callback,
342       const std::string& command_prefix) WARN_UNUSED_RESULT = 0;
343 
344   // Returns the current CRWWebViewProxy object.
345   virtual CRWWebViewProxyType GetWebViewProxy() const = 0;
346 
347   // Typically an embedder will:
348   //    - Implement this method to receive notification of changes to the page's
349   //      |VisibleSecurityState|, updating security UI (e.g. a lock icon) to
350   //      reflect the current security state of the page.
351   // ...and optionally:
352   //    - Invoke this method upon detection of an event that will change
353   //      the security state (e.g. a non-secure form element is edited).
354   virtual void DidChangeVisibleSecurityState() = 0;
355 
356   virtual InterfaceBinder* GetInterfaceBinderForMainFrame();
357 
358   // Whether this WebState was created with an opener.
359   // See CreateParams::created_with_opener for more details.
360   virtual bool HasOpener() const = 0;
361   virtual void SetHasOpener(bool has_opener) = 0;
362 
363   // Callback used to handle snapshots. The parameter is the snapshot image.
364   typedef base::RepeatingCallback<void(const gfx::Image&)> SnapshotCallback;
365 
366   // Returns whether TakeSnapshot() can be executed.  The API may be disabled if
367   // the WKWebView IPC mechanism is blocked due to an outstanding JavaScript
368   // dialog.
369   virtual bool CanTakeSnapshot() const = 0;
370 
371   // Takes a snapshot of this WebState with |rect|. |rect| should be specified
372   // in the coordinate system of the view returned by GetView(). |callback| is
373   // asynchronously invoked after performing the snapshot. Prior to iOS 11, the
374   // callback is invoked with a nil snapshot.
375   virtual void TakeSnapshot(const gfx::RectF& rect,
376                             SnapshotCallback callback) = 0;
377 
378   // Creates PDF representation of the web page and invokes the |callback| with
379   // the NSData of the PDF or nil if a PDF couldn't be generated.
380   virtual void CreateFullPagePdf(
381       base::OnceCallback<void(NSData*)> callback) = 0;
382 
383   // Adds and removes observers for page navigation notifications. The order in
384   // which notifications are sent to observers is undefined. Clients must be
385   // sure to remove the observer before they go away.
386   virtual void AddObserver(WebStateObserver* observer) = 0;
387   virtual void RemoveObserver(WebStateObserver* observer) = 0;
388 
389   // Instructs the delegate to close this web state. Called when the page calls
390   // wants to close self by calling window.close() JavaScript API.
391   virtual void CloseWebState() = 0;
392 
393  protected:
394   friend class WebStatePolicyDecider;
395 
396   // Adds and removes policy deciders for navigation actions. The order in which
397   // deciders are called is undefined, and will stop on the first decider that
398   // refuses a navigation. Clients must be sure to remove the deciders before
399   // they go away.
400   virtual void AddPolicyDecider(WebStatePolicyDecider* decider) = 0;
401   virtual void RemovePolicyDecider(WebStatePolicyDecider* decider) = 0;
402 
WebState()403   WebState() {}
404 
405  private:
406   DISALLOW_COPY_AND_ASSIGN(WebState);
407 };
408 
409 }  // namespace web
410 
411 #endif  // IOS_WEB_PUBLIC_WEB_STATE_H_
412