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 CONTENT_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_H_
6 #define CONTENT_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_H_
7 
8 #include <stdint.h>
9 
10 #include "base/compiler_specific.h"
11 #include "base/macros.h"
12 #include "base/memory/read_only_shared_memory_region.h"
13 #include "base/optional.h"
14 #include "base/strings/string16.h"
15 #include "content/common/content_export.h"
16 #include "ipc/ipc_listener.h"
17 #include "ipc/ipc_sender.h"
18 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
19 #include "mojo/public/cpp/system/message_pipe.h"
20 #include "services/network/public/mojom/url_response_head.mojom-forward.h"
21 #include "third_party/blink/public/common/loader/loading_behavior_flag.h"
22 #include "third_party/blink/public/common/loader/previews_state.h"
23 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
24 #include "third_party/blink/public/mojom/use_counter/css_property_id.mojom.h"
25 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
26 #include "third_party/blink/public/platform/web_vector.h"
27 #include "third_party/blink/public/web/web_local_frame_client.h"
28 #include "third_party/blink/public/web/web_meaningful_layout.h"
29 #include "third_party/blink/public/web/web_navigation_type.h"
30 #include "ui/accessibility/ax_mode.h"
31 #include "ui/base/page_transition_types.h"
32 #include "v8/include/v8.h"
33 
34 class GURL;
35 
36 namespace blink {
37 class WebDocumentLoader;
38 class WebElement;
39 class WebFormElement;
40 class WebString;
41 class WebWorkerFetchContext;
42 }  // namespace blink
43 
44 namespace network {
45 struct URLLoaderCompletionStatus;
46 }  // namespace network
47 
48 namespace content {
49 
50 class RendererPpapiHost;
51 class RenderFrame;
52 class RenderFrameImpl;
53 
54 // Base class for objects that want to filter incoming IPCs, and also get
55 // notified of changes to the frame.
56 class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
57                                            public IPC::Sender {
58  public:
59   // A subclass can use this to delete itself. If it does not, the subclass must
60   // always null-check each call to render_frame() because the RenderFrame can
61   // go away at any time.
62   virtual void OnDestruct() = 0;
63 
64   // Called when a Pepper plugin is created.
DidCreatePepperPlugin(RendererPpapiHost * host)65   virtual void DidCreatePepperPlugin(RendererPpapiHost* host) {}
66 
67   // Called when a load is explicitly stopped by the user or browser.
OnStop()68   virtual void OnStop() {}
69 
70   // Called when the RenderFrame visiblity is changed.
WasHidden()71   virtual void WasHidden() {}
WasShown()72   virtual void WasShown() {}
73 
74   // Navigation callbacks.
75   //
76   // Each navigation starts with a DidStartNavigation call. Then it may be
77   // followed by a ReadyToCommitNavigation (if the navigation has succeeded),
78   // and should always end with a DidFinishNavigation.
79   // TODO(dgozman): ReadyToCommitNavigation will be removed soon.
80   //
81   // Unfortunately, this is currently a mess. For example, some started
82   // navigations which did not commit won't receive any further notifications.
83   // DidCommitProvisionalLoad will be called for same-document navigations,
84   // without any other notifications. DidFailProvisionalLoad will be called
85   // when committing error pages, in addition to all the methods (start, ready,
86   // commit) for the error page load itself.
87 
88   // Called when the RenderFrame has started a navigation.
89   // |url| is a url being navigated to. Note that final url might be different
90   // due to redirects.
91   // |navigation_type| is only present for renderer-initiated navigations, e.g.
92   // JavaScript call, link click, form submit. User-initiated navigations from
93   // the browser process (e.g. by typing a url) won't have a navigation type.
DidStartNavigation(const GURL & url,base::Optional<blink::WebNavigationType> navigation_type)94   virtual void DidStartNavigation(
95       const GURL& url,
96       base::Optional<blink::WebNavigationType> navigation_type) {}
97 
98   // Called when a navigation has just committed and |document_loader|
99   // will start loading a new document in the RenderFrame.
100   // TODO(dgozman): the name does not match functionality anymore, we should
101   // merge this with DidCommitProvisionalLoad, which will become
102   // DidFinishNavigation.
ReadyToCommitNavigation(blink::WebDocumentLoader * document_loader)103   virtual void ReadyToCommitNavigation(
104       blink::WebDocumentLoader* document_loader) {}
105 
106   // Called when a RenderFrame's page lifecycle state gets updated.
DidSetPageLifecycleState()107   virtual void DidSetPageLifecycleState() {}
108 
109   // These match the Blink API notifications
DidCreateNewDocument()110   virtual void DidCreateNewDocument() {}
DidCreateDocumentElement()111   virtual void DidCreateDocumentElement() {}
112   // TODO(dgozman): replace next two methods with DidFinishNavigation.
113   // DidCommitProvisionalLoad is only called for new-document navigations.
114   // Use DidFinishSameDocumentNavigation for same-document navigations.
DidCommitProvisionalLoad(ui::PageTransition transition)115   virtual void DidCommitProvisionalLoad(ui::PageTransition transition) {}
DidFailProvisionalLoad()116   virtual void DidFailProvisionalLoad() {}
DidFinishLoad()117   virtual void DidFinishLoad() {}
DidFinishDocumentLoad()118   virtual void DidFinishDocumentLoad() {}
DidHandleOnloadEvents()119   virtual void DidHandleOnloadEvents() {}
DidCreateScriptContext(v8::Local<v8::Context> context,int32_t world_id)120   virtual void DidCreateScriptContext(v8::Local<v8::Context> context,
121                                       int32_t world_id) {}
WillReleaseScriptContext(v8::Local<v8::Context> context,int32_t world_id)122   virtual void WillReleaseScriptContext(v8::Local<v8::Context> context,
123                                         int32_t world_id) {}
DidClearWindowObject()124   virtual void DidClearWindowObject() {}
DidChangeScrollOffset()125   virtual void DidChangeScrollOffset() {}
WillSendSubmitEvent(const blink::WebFormElement & form)126   virtual void WillSendSubmitEvent(const blink::WebFormElement& form) {}
WillSubmitForm(const blink::WebFormElement & form)127   virtual void WillSubmitForm(const blink::WebFormElement& form) {}
DidMatchCSS(const blink::WebVector<blink::WebString> & newly_matching_selectors,const blink::WebVector<blink::WebString> & stopped_matching_selectors)128   virtual void DidMatchCSS(
129       const blink::WebVector<blink::WebString>& newly_matching_selectors,
130       const blink::WebVector<blink::WebString>& stopped_matching_selectors) {}
131 
132   // Called when same-document navigation finishes.
133   // This is the only callback for same-document navigations,
134   // DidStartNavigation and ReadyToCommitNavigation are not called.
135   //
136   // Same-document navigation is typically initiated by an anchor click
137   // (that usually results in the page scrolling to the anchor) or a
138   // history web API manipulation.
139   //
140   // However, it could be some rare case like user changing #hash in the url
141   // bar or history restore for subframe or anything else that was classified
142   // as same-document.
DidFinishSameDocumentNavigation()143   virtual void DidFinishSameDocumentNavigation() {}
144 
145   // Called when this frame has been detached from the view. This *will* be
146   // called for child frames when a parent frame is detached. Since the frame is
147   // already detached from the DOM at this time, it should not be inspected.
WillDetach()148   virtual void WillDetach() {}
149 
150   // Called when we receive a console message from Blink for which we requested
151   // extra details (like the stack trace). |message| is the error message,
152   // |source| is the Blink-reported source of the error (either external or
153   // internal), and |stack_trace| is the stack trace of the error in a
154   // human-readable format (each frame is formatted as
155   // "\n    at function_name (source:line_number:column_number)").
DetailedConsoleMessageAdded(const base::string16 & message,const base::string16 & source,const base::string16 & stack_trace,uint32_t line_number,int32_t severity_level)156   virtual void DetailedConsoleMessageAdded(const base::string16& message,
157                                            const base::string16& source,
158                                            const base::string16& stack_trace,
159                                            uint32_t line_number,
160                                            int32_t severity_level) {}
161 
162   // Called when an interesting (from document lifecycle perspective),
163   // compositor-driven layout had happened. This is a reasonable hook to use
164   // to inspect the document and layout information, since it is in a clean
165   // state and you won't accidentally force new layouts.
166   // The interestingness of layouts is explained in WebMeaningfulLayout.h.
DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type)167   virtual void DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) {}
168 
169   // Notifications when |PerformanceTiming| data becomes available
DidChangePerformanceTiming()170   virtual void DidChangePerformanceTiming() {}
171 
172   // Notifications When an input delay data becomes available.
DidObserveInputDelay(base::TimeDelta input_delay)173   virtual void DidObserveInputDelay(base::TimeDelta input_delay) {}
174 
175   // Notification When the First Scroll Delay becomes available.
DidObserveFirstScrollDelay(base::TimeDelta first_scroll_delay)176   virtual void DidObserveFirstScrollDelay(base::TimeDelta first_scroll_delay) {}
177 
178   // Notifications when a cpu timing update becomes available, when a frame
179   // has performed at least 100ms of tasks.
DidChangeCpuTiming(base::TimeDelta time)180   virtual void DidChangeCpuTiming(base::TimeDelta time) {}
181 
182   // Notification when the renderer uses a particular code path during a page
183   // load. This is used for metrics collection.
DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior)184   virtual void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) {}
185 
186   // Notification when the renderer observes a new use counter usage during a
187   // page load. This is used for UseCounter metrics.
DidObserveNewFeatureUsage(blink::mojom::WebFeature feature)188   virtual void DidObserveNewFeatureUsage(blink::mojom::WebFeature feature) {}
DidObserveNewCssPropertyUsage(blink::mojom::CSSSampleId css_property,bool is_animated)189   virtual void DidObserveNewCssPropertyUsage(
190       blink::mojom::CSSSampleId css_property,
191       bool is_animated) {}
192 
193   // Reports that visible elements in the frame shifted (bit.ly/lsm-explainer).
194   // This is called once for each animation frame containing any layout shift,
195   // and receives the layout shift (LS) score for that frame.  The cumulative
196   // layout shift (CLS) score can be inferred by summing the LS scores.
197   // |after_input_or_scroll| indicates whether the given |score| was observed
198   // after an input or scroll occurred in the associated document.
DidObserveLayoutShift(double score,bool after_input_or_scroll)199   virtual void DidObserveLayoutShift(double score, bool after_input_or_scroll) {
200   }
201 
202   // Reports the number of LayoutBlock creation, and LayoutObject::UpdateLayout
203   // calls. All values are deltas since the last calls of this function.
DidObserveLayoutNg(uint32_t all_block_count,uint32_t ng_block_count,uint32_t all_call_count,uint32_t ng_call_count)204   virtual void DidObserveLayoutNg(uint32_t all_block_count,
205                                   uint32_t ng_block_count,
206                                   uint32_t all_call_count,
207                                   uint32_t ng_call_count) {}
208 
209   // Reports lazy loaded behavior when the frame or image is fully deferred or
210   // if the frame or image is loaded after being deferred by lazy load.
211   // Called every time the behavior occurs. This does not apply to image
212   // requests for placeholder images.
DidObserveLazyLoadBehavior(blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior)213   virtual void DidObserveLazyLoadBehavior(
214       blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {}
215 
216   // Notification when the renderer a response started, completed or canceled.
217   // Complete or Cancel is guaranteed to be called for a response that started.
218   // |request_id| uniquely identifies the request within this render frame.
219   // |previews_state| is the PreviewsState if the request is a sub-resource. For
220   // Document resources, |previews_state| should be reported as PREVIEWS_OFF.
DidStartResponse(const GURL & response_url,int request_id,const network::mojom::URLResponseHead & response_head,network::mojom::RequestDestination request_destination,blink::PreviewsState previews_state)221   virtual void DidStartResponse(
222       const GURL& response_url,
223       int request_id,
224       const network::mojom::URLResponseHead& response_head,
225       network::mojom::RequestDestination request_destination,
226       blink::PreviewsState previews_state) {}
DidCompleteResponse(int request_id,const network::URLLoaderCompletionStatus & status)227   virtual void DidCompleteResponse(
228       int request_id,
229       const network::URLLoaderCompletionStatus& status) {}
DidCancelResponse(int request_id)230   virtual void DidCancelResponse(int request_id) {}
231 
232   // Reports that a resource was loaded from the blink memory cache.
233   // |request_id| uniquely identifies this resource within this render frame.
234   // |from_archive| indicates if the resource originated from a MHTML archive.
DidLoadResourceFromMemoryCache(const GURL & response_url,int request_id,int64_t encoded_body_length,const std::string & mime_type,bool from_archive)235   virtual void DidLoadResourceFromMemoryCache(const GURL& response_url,
236                                               int request_id,
237                                               int64_t encoded_body_length,
238                                               const std::string& mime_type,
239                                               bool from_archive) {}
240 
241   // Notification when the renderer observes data used during the page load.
242   // This is used for page load metrics. |received_data_length| is the received
243   // network bytes. |resource_id| uniquely identifies the resource within this
244   // render frame.
DidReceiveTransferSizeUpdate(int resource_id,int received_data_length)245   virtual void DidReceiveTransferSizeUpdate(int resource_id,
246                                             int received_data_length) {}
247 
248   // Called when the focused element has changed to |element|.
FocusedElementChanged(const blink::WebElement & element)249   virtual void FocusedElementChanged(const blink::WebElement& element) {}
250 
251   // Called when accessibility is enabled or disabled.
AccessibilityModeChanged(const ui::AXMode & mode)252   virtual void AccessibilityModeChanged(const ui::AXMode& mode) {}
253 
254   // Called when script in the page calls window.print().
ScriptedPrint(bool user_initiated)255   virtual void ScriptedPrint(bool user_initiated) {}
256 
257   // Called when draggable regions change.
DraggableRegionsChanged()258   virtual void DraggableRegionsChanged() {}
259 
260   // Called when a worker fetch context will be created.
WillCreateWorkerFetchContext(blink::WebWorkerFetchContext *)261   virtual void WillCreateWorkerFetchContext(blink::WebWorkerFetchContext*) {}
262 
263   // Called when a frame's intersection with the main frame changes.
OnMainFrameIntersectionChanged(const blink::WebRect & intersect_rect)264   virtual void OnMainFrameIntersectionChanged(
265       const blink::WebRect& intersect_rect) {}
266 
267   // Called to give the embedder an opportunity to bind an interface request
268   // for a frame. If the request can be bound, |interface_pipe| will be taken.
OnInterfaceRequestForFrame(const std::string & interface_name,mojo::ScopedMessagePipeHandle * interface_pipe)269   virtual void OnInterfaceRequestForFrame(
270       const std::string& interface_name,
271       mojo::ScopedMessagePipeHandle* interface_pipe) {}
272 
273   // Similar to above but for handling Channel-associated interface requests.
274   // Returns |true| if the request is handled by the implementation (taking
275   // ownership of |*handle|) and |false| otherwise (leaving |*handle|
276   // unmodified).
277   virtual bool OnAssociatedInterfaceRequestForFrame(
278       const std::string& interface_name,
279       mojo::ScopedInterfaceEndpointHandle* handle);
280 
281   // Called when a page's mobile friendliness changed.
OnMobileFriendlinessChanged(const blink::MobileFriendliness &)282   virtual void OnMobileFriendlinessChanged(const blink::MobileFriendliness&) {}
283 
284   // The smoothness metrics is shared over shared-memory. The interested
285   // observer should invalidate |shared_memory| (by std::move()'ing it), and
286   // return true. All other observers should return false (default).
287   virtual bool SetUpSmoothnessReporting(
288       base::ReadOnlySharedMemoryRegion& shared_memory);
289 
290   // IPC::Listener implementation.
291   bool OnMessageReceived(const IPC::Message& message) override;
292 
293   // IPC::Sender implementation.
294   bool Send(IPC::Message* message) override;
295 
296   RenderFrame* render_frame() const;
routing_id()297   int routing_id() const { return routing_id_; }
298 
299  protected:
300   explicit RenderFrameObserver(RenderFrame* render_frame);
301   ~RenderFrameObserver() override;
302 
303  private:
304   friend class RenderFrameImpl;
305 
306   // This is called by the RenderFrame when it's going away so that this object
307   // can null out its pointer.
308   void RenderFrameGone();
309 
310   RenderFrame* render_frame_;
311   // The routing ID of the associated RenderFrame.
312   int routing_id_;
313 
314   DISALLOW_COPY_AND_ASSIGN(RenderFrameObserver);
315 };
316 
317 }  // namespace content
318 
319 #endif  // CONTENT_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_H_
320