extension_frame_helper.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. #ifndef EXTENSIONS_RENDERER_EXTENSION_FRAME_HELPER_H_
  5. #define EXTENSIONS_RENDERER_EXTENSION_FRAME_HELPER_H_
  6. #include <string>
  7. #include <vector>
  8. #include "base/callback_forward.h"
  9. #include "base/memory/weak_ptr.h"
  10. #include "base/values.h"
  11. #include "content/public/renderer/render_frame_observer.h"
  12. #include "content/public/renderer/render_frame_observer_tracker.h"
  13. #include "extensions/common/mojom/frame.mojom.h"
  14. #include "extensions/common/mojom/view_type.mojom.h"
  15. #include "mojo/public/cpp/bindings/associated_receiver.h"
  16. #include "mojo/public/cpp/bindings/associated_remote.h"
  17. #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
  18. #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
  19. #include "v8/include/v8-forward.h"
  20. struct ExtensionMsg_ExternalConnectionInfo;
  21. struct ExtensionMsg_TabConnectionInfo;
  22. namespace extensions {
  23. class Dispatcher;
  24. struct Message;
  25. struct PortId;
  26. class ScriptContext;
  27. // RenderFrame-level plumbing for extension features.
  28. class ExtensionFrameHelper
  29. : public content::RenderFrameObserver,
  30. public content::RenderFrameObserverTracker<ExtensionFrameHelper>,
  31. public mojom::LocalFrame {
  32. public:
  33. ExtensionFrameHelper(content::RenderFrame* render_frame,
  34. Dispatcher* extension_dispatcher);
  35. ExtensionFrameHelper(const ExtensionFrameHelper&) = delete;
  36. ExtensionFrameHelper& operator=(const ExtensionFrameHelper&) = delete;
  37. ~ExtensionFrameHelper() override;
  38. // Returns a list of extension RenderFrames that match the given filter
  39. // criteria. A |browser_window_id| of extension_misc::kUnknownWindowId
  40. // specifies "all", as does a |view_type| of mojom::ViewType::kInvalid.
  41. static std::vector<content::RenderFrame*> GetExtensionFrames(
  42. const std::string& extension_id,
  43. int browser_window_id,
  44. int tab_id,
  45. mojom::ViewType view_type);
  46. // Same as above, but returns a v8::Array of the v8 global objects for those
  47. // frames, and only includes outermost main frames. Note: This only returns
  48. // contexts that are accessible by |context|, and |context| must be the
  49. // current context.
  50. // Returns an empty v8::Array if no frames are found.
  51. static v8::Local<v8::Array> GetV8MainFrames(v8::Local<v8::Context> context,
  52. const std::string& extension_id,
  53. int browser_window_id,
  54. int tab_id,
  55. mojom::ViewType view_type);
  56. // Returns the main frame of the extension's background page, or null if there
  57. // isn't one in this process.
  58. static content::RenderFrame* GetBackgroundPageFrame(
  59. const std::string& extension_id);
  60. // Same as above, but returns the background page's main frame, or
  61. // v8::Undefined if there is none. Note: This will assert that the
  62. // isolate's current context can access the returned object; callers should
  63. // ensure that the current context is correct.
  64. static v8::Local<v8::Value> GetV8BackgroundPageMainFrame(
  65. v8::Isolate* isolate,
  66. const std::string& extension_id);
  67. // Finds a neighboring extension frame with the same extension as the one
  68. // owning |relative_to_frame| (if |relative_to_frame| is not an extension
  69. // frame, returns nullptr). Pierces the browsing instance boundary because
  70. // certain extensions rely on this behavior.
  71. // TODO(devlin, lukasza): https://crbug.com/786411: Remove this behavior, and
  72. // make extensions follow the web standard for finding frames or use an
  73. // explicit API.
  74. static content::RenderFrame* FindFrame(
  75. content::RenderFrame* relative_to_frame,
  76. const std::string& name);
  77. // Returns true if the given |context| is for any frame in the extension's
  78. // event page.
  79. // TODO(devlin): This isn't really used properly, and should probably be
  80. // deleted.
  81. static bool IsContextForEventPage(const ScriptContext* context);
  82. mojom::ViewType view_type() const { return view_type_; }
  83. int tab_id() const { return tab_id_; }
  84. int browser_window_id() const { return browser_window_id_; }
  85. bool did_create_current_document_element() const {
  86. return did_create_current_document_element_;
  87. }
  88. // mojom::LocalFrame:
  89. void SetFrameName(const std::string& name) override;
  90. void SetSpatialNavigationEnabled(bool enabled) override;
  91. void SetTabId(int32_t id) override;
  92. void AppWindowClosed(bool send_onclosed) override;
  93. void NotifyRenderViewType(mojom::ViewType view_type) override;
  94. void MessageInvoke(const std::string& extension_id,
  95. const std::string& module_name,
  96. const std::string& function_name,
  97. base::Value::List args) override;
  98. void ExecuteCode(mojom::ExecuteCodeParamsPtr param,
  99. ExecuteCodeCallback callback) override;
  100. void ExecuteDeclarativeScript(int32_t tab_id,
  101. const std::string& extension_id,
  102. const std::string& script_id,
  103. const GURL& url) override;
  104. void UpdateBrowserWindowId(int32_t window_id) override;
  105. void NotifyDidCreateScriptContext(int32_t world_id);
  106. bool did_create_script_context() const { return did_create_script_context_; }
  107. // Called when the document element has been inserted in this frame. This
  108. // method may invoke untrusted JavaScript code that invalidate the frame and
  109. // this ExtensionFrameHelper.
  110. void RunScriptsAtDocumentStart();
  111. // Called after the DOMContentLoaded event has fired.
  112. void RunScriptsAtDocumentEnd();
  113. // Called before the window.onload event is fired.
  114. void RunScriptsAtDocumentIdle();
  115. // Schedule a callback, to be run at the next RunScriptsAtDocumentStart
  116. // notification. Only call this when you are certain that there will be such a
  117. // notification, e.g. from RenderFrameObserver::DidCreateDocumentElement.
  118. // Otherwise the callback is never invoked, or invoked for a document that you
  119. // were not expecting.
  120. void ScheduleAtDocumentStart(base::OnceClosure callback);
  121. // Schedule a callback, to be run at the next RunScriptsAtDocumentEnd call.
  122. void ScheduleAtDocumentEnd(base::OnceClosure callback);
  123. // Schedule a callback, to be run at the next RunScriptsAtDocumentIdle call.
  124. void ScheduleAtDocumentIdle(base::OnceClosure callback);
  125. mojom::LocalFrameHost* GetLocalFrameHost();
  126. private:
  127. void BindLocalFrame(
  128. mojo::PendingAssociatedReceiver<mojom::LocalFrame> receiver);
  129. // RenderFrameObserver implementation.
  130. void DidCreateDocumentElement() override;
  131. void DidCreateNewDocument() override;
  132. void ReadyToCommitNavigation(
  133. blink::WebDocumentLoader* document_loader) override;
  134. void DidCommitProvisionalLoad(ui::PageTransition transition) override;
  135. void DidCreateScriptContext(v8::Local<v8::Context>,
  136. int32_t world_id) override;
  137. void WillReleaseScriptContext(v8::Local<v8::Context>,
  138. int32_t world_id) override;
  139. bool OnMessageReceived(const IPC::Message& message) override;
  140. void OnDestruct() override;
  141. void DraggableRegionsChanged() override;
  142. void DidClearWindowObject() override;
  143. // IPC handlers.
  144. void OnExtensionValidateMessagePort(int worker_thread_id, const PortId& id);
  145. void OnExtensionDispatchOnConnect(
  146. int worker_thread_id,
  147. const PortId& target_port_id,
  148. const std::string& channel_name,
  149. const ExtensionMsg_TabConnectionInfo& source,
  150. const ExtensionMsg_ExternalConnectionInfo& info);
  151. void OnExtensionDeliverMessage(int worker_thread_id,
  152. const PortId& target_port_id,
  153. const Message& message);
  154. void OnExtensionDispatchOnDisconnect(int worker_thread_id,
  155. const PortId& id,
  156. const std::string& error_message);
  157. // Type of view associated with the RenderFrame.
  158. mojom::ViewType view_type_ = mojom::ViewType::kInvalid;
  159. // The id of the tab the render frame is attached to.
  160. int tab_id_ = -1;
  161. // The id of the browser window the render frame is attached to.
  162. int browser_window_id_ = -1;
  163. Dispatcher* extension_dispatcher_;
  164. // Whether or not the current document element has been created. This starts
  165. // true as the initial empty document is already created when this class is
  166. // instantiated.
  167. // TODO(danakj): Does this still need to be tracked? We now have consisitent
  168. // notifications for initial empty documents on all frames.
  169. bool did_create_current_document_element_ = true;
  170. // Callbacks to be run at the next RunScriptsAtDocumentStart notification.
  171. std::vector<base::OnceClosure> document_element_created_callbacks_;
  172. // Callbacks to be run at the next RunScriptsAtDocumentEnd notification.
  173. std::vector<base::OnceClosure> document_load_finished_callbacks_;
  174. // Callbacks to be run at the next RunScriptsAtDocumentIdle notification.
  175. std::vector<base::OnceClosure> document_idle_callbacks_;
  176. bool delayed_main_world_script_initialization_ = false;
  177. // Whether or not a DocumentLoader has been created at least once for this
  178. // RenderFrame.
  179. // Note: Chrome Apps intentionally do not support new navigations. When a
  180. // navigation happens, it is either the initial one or a reload.
  181. bool has_started_first_navigation_ = false;
  182. bool did_create_script_context_ = false;
  183. // Whether we are currently initializing the main world script context.
  184. bool is_initializing_main_world_script_context_ = false;
  185. mojo::AssociatedRemote<mojom::LocalFrameHost> local_frame_host_remote_;
  186. mojo::AssociatedReceiver<mojom::LocalFrame> local_frame_receiver_{this};
  187. base::WeakPtrFactory<ExtensionFrameHelper> weak_ptr_factory_{this};
  188. };
  189. } // namespace extensions
  190. #endif // EXTENSIONS_RENDERER_EXTENSION_FRAME_HELPER_H_