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.
5 #include "extensions/renderer/extension_frame_helper.h"
7 #include "content/public/renderer/render_frame.h"
8 #include "extensions/common/api/messaging/message.h"
9 #include "extensions/common/constants.h"
10 #include "extensions/common/extension_messages.h"
11 #include "extensions/common/manifest_handlers/background_info.h"
12 #include "extensions/renderer/console.h"
13 #include "extensions/renderer/content_watcher.h"
14 #include "extensions/renderer/dispatcher.h"
15 #include "extensions/renderer/messaging_bindings.h"
16 #include "extensions/renderer/script_context.h"
17 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
18 #include "third_party/WebKit/public/web/WebDocument.h"
19 #include "third_party/WebKit/public/web/WebLocalFrame.h"
21 namespace extensions
{
25 base::LazyInstance
<std::set
<const ExtensionFrameHelper
*>> g_frame_helpers
=
26 LAZY_INSTANCE_INITIALIZER
;
28 // Returns true if the render frame corresponding with |frame_helper| matches
29 // the given criteria.
30 bool RenderFrameMatches(const ExtensionFrameHelper
* frame_helper
,
31 ViewType match_view_type
,
33 const std::string
& match_extension_id
) {
34 if (match_view_type
!= VIEW_TYPE_INVALID
&&
35 frame_helper
->view_type() != match_view_type
)
37 GURL url
= frame_helper
->render_frame()->GetWebFrame()->document().url();
38 if (!url
.SchemeIs(kExtensionScheme
))
40 if (url
.host() != match_extension_id
)
42 if (match_window_id
!= extension_misc::kUnknownWindowId
&&
43 frame_helper
->browser_window_id() != match_window_id
)
50 ExtensionFrameHelper::ExtensionFrameHelper(content::RenderFrame
* render_frame
,
51 Dispatcher
* extension_dispatcher
)
52 : content::RenderFrameObserver(render_frame
),
53 content::RenderFrameObserverTracker
<ExtensionFrameHelper
>(render_frame
),
54 view_type_(VIEW_TYPE_INVALID
),
56 browser_window_id_(-1),
57 extension_dispatcher_(extension_dispatcher
) {
58 g_frame_helpers
.Get().insert(this);
61 ExtensionFrameHelper::~ExtensionFrameHelper() {
62 g_frame_helpers
.Get().erase(this);
66 std::vector
<content::RenderFrame
*> ExtensionFrameHelper::GetExtensionFrames(
67 const std::string
& extension_id
,
68 int browser_window_id
,
70 std::vector
<content::RenderFrame
*> render_frames
;
71 for (const ExtensionFrameHelper
* helper
: g_frame_helpers
.Get()) {
72 if (RenderFrameMatches(helper
, view_type
, browser_window_id
, extension_id
))
73 render_frames
.push_back(helper
->render_frame());
79 content::RenderFrame
* ExtensionFrameHelper::GetBackgroundPageFrame(
80 const std::string
& extension_id
) {
81 for (const ExtensionFrameHelper
* helper
: g_frame_helpers
.Get()) {
82 if (RenderFrameMatches(helper
, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
,
83 extension_misc::kUnknownWindowId
, extension_id
)) {
84 blink::WebLocalFrame
* web_frame
= helper
->render_frame()->GetWebFrame();
85 // Check if this is the top frame.
86 if (web_frame
->top() == web_frame
)
87 return helper
->render_frame();
94 bool ExtensionFrameHelper::IsContextForEventPage(const ScriptContext
* context
) {
95 content::RenderFrame
* render_frame
= context
->GetRenderFrame();
96 return context
->extension() && render_frame
&&
97 BackgroundInfo::HasLazyBackgroundPage(context
->extension()) &&
98 ExtensionFrameHelper::Get(render_frame
)->view_type() ==
99 VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
;
102 void ExtensionFrameHelper::DidCreateDocumentElement() {
103 extension_dispatcher_
->DidCreateDocumentElement(
104 render_frame()->GetWebFrame());
107 void ExtensionFrameHelper::DidMatchCSS(
108 const blink::WebVector
<blink::WebString
>& newly_matching_selectors
,
109 const blink::WebVector
<blink::WebString
>& stopped_matching_selectors
) {
110 extension_dispatcher_
->content_watcher()->DidMatchCSS(
111 render_frame()->GetWebFrame(), newly_matching_selectors
,
112 stopped_matching_selectors
);
115 void ExtensionFrameHelper::DidCreateScriptContext(
116 v8::Local
<v8::Context
> context
,
119 extension_dispatcher_
->DidCreateScriptContext(
120 render_frame()->GetWebFrame(), context
, extension_group
, world_id
);
123 void ExtensionFrameHelper::WillReleaseScriptContext(
124 v8::Local
<v8::Context
> context
,
126 extension_dispatcher_
->WillReleaseScriptContext(
127 render_frame()->GetWebFrame(), context
, world_id
);
130 bool ExtensionFrameHelper::OnMessageReceived(const IPC::Message
& message
) {
132 IPC_BEGIN_MESSAGE_MAP(ExtensionFrameHelper
, message
)
133 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect
,
134 OnExtensionDispatchOnConnect
)
135 IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage
, OnExtensionDeliverMessage
)
136 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect
,
137 OnExtensionDispatchOnDisconnect
)
138 IPC_MESSAGE_HANDLER(ExtensionMsg_SetTabId
, OnExtensionSetTabId
)
139 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateBrowserWindowId
,
140 OnUpdateBrowserWindowId
)
141 IPC_MESSAGE_HANDLER(ExtensionMsg_SetMainFrameExtensionOwner
,
142 OnSetMainFrameExtensionOwner
)
143 IPC_MESSAGE_HANDLER(ExtensionMsg_NotifyRenderViewType
,
144 OnNotifyRendererViewType
)
145 IPC_MESSAGE_HANDLER(ExtensionMsg_Response
, OnExtensionResponse
)
146 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke
, OnExtensionMessageInvoke
)
147 IPC_MESSAGE_UNHANDLED(handled
= false)
148 IPC_END_MESSAGE_MAP()
152 void ExtensionFrameHelper::OnExtensionDispatchOnConnect(
154 const std::string
& channel_name
,
155 const ExtensionMsg_TabConnectionInfo
& source
,
156 const ExtensionMsg_ExternalConnectionInfo
& info
,
157 const std::string
& tls_channel_id
) {
158 MessagingBindings::DispatchOnConnect(
159 extension_dispatcher_
->script_context_set(),
168 void ExtensionFrameHelper::OnExtensionDeliverMessage(int target_id
,
169 const Message
& message
) {
170 MessagingBindings::DeliverMessage(
171 extension_dispatcher_
->script_context_set(), target_id
, message
,
175 void ExtensionFrameHelper::OnExtensionDispatchOnDisconnect(
177 const std::string
& error_message
) {
178 MessagingBindings::DispatchOnDisconnect(
179 extension_dispatcher_
->script_context_set(), port_id
, error_message
,
183 void ExtensionFrameHelper::OnExtensionSetTabId(int tab_id
) {
184 CHECK_EQ(tab_id_
, -1);
189 void ExtensionFrameHelper::OnUpdateBrowserWindowId(int browser_window_id
) {
190 browser_window_id_
= browser_window_id
;
193 void ExtensionFrameHelper::OnSetMainFrameExtensionOwner(
194 const std::string
& extension_id
) {
195 tab_extension_owner_id_
= extension_id
;
198 void ExtensionFrameHelper::OnNotifyRendererViewType(ViewType type
) {
199 // TODO(devlin): It'd be really nice to be able to
200 // DCHECK_EQ(VIEW_TYPE_INVALID, view_type_) here.
204 void ExtensionFrameHelper::OnExtensionResponse(int request_id
,
206 const base::ListValue
& response
,
207 const std::string
& error
) {
208 extension_dispatcher_
->OnExtensionResponse(request_id
,
214 void ExtensionFrameHelper::OnExtensionMessageInvoke(
215 const std::string
& extension_id
,
216 const std::string
& module_name
,
217 const std::string
& function_name
,
218 const base::ListValue
& args
,
220 extension_dispatcher_
->InvokeModuleSystemMethod(render_frame(), extension_id
,
221 module_name
, function_name
,
225 } // namespace extensions