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/dispatcher.h"
14 #include "extensions/renderer/messaging_bindings.h"
15 #include "extensions/renderer/script_context.h"
16 #include "third_party/WebKit/public/web/WebConsoleMessage.h"
17 #include "third_party/WebKit/public/web/WebDocument.h"
18 #include "third_party/WebKit/public/web/WebLocalFrame.h"
20 namespace extensions
{
24 base::LazyInstance
<std::set
<const ExtensionFrameHelper
*>> g_frame_helpers
=
25 LAZY_INSTANCE_INITIALIZER
;
27 // Returns true if the render frame corresponding with |frame_helper| matches
28 // the given criteria.
29 bool RenderFrameMatches(const ExtensionFrameHelper
* frame_helper
,
30 ViewType match_view_type
,
32 const std::string
& match_extension_id
) {
33 if (match_view_type
!= VIEW_TYPE_INVALID
&&
34 frame_helper
->view_type() != match_view_type
)
36 GURL url
= frame_helper
->render_frame()->GetWebFrame()->document().url();
37 if (!url
.SchemeIs(kExtensionScheme
))
39 if (url
.host() != match_extension_id
)
41 if (match_window_id
!= extension_misc::kUnknownWindowId
&&
42 frame_helper
->browser_window_id() != match_window_id
)
49 ExtensionFrameHelper::ExtensionFrameHelper(content::RenderFrame
* render_frame
,
50 Dispatcher
* extension_dispatcher
)
51 : content::RenderFrameObserver(render_frame
),
52 content::RenderFrameObserverTracker
<ExtensionFrameHelper
>(render_frame
),
53 view_type_(VIEW_TYPE_INVALID
),
55 browser_window_id_(-1),
56 extension_dispatcher_(extension_dispatcher
) {
57 g_frame_helpers
.Get().insert(this);
60 ExtensionFrameHelper::~ExtensionFrameHelper() {
61 g_frame_helpers
.Get().erase(this);
65 std::vector
<content::RenderFrame
*> ExtensionFrameHelper::GetExtensionFrames(
66 const std::string
& extension_id
,
67 int browser_window_id
,
69 std::vector
<content::RenderFrame
*> render_frames
;
70 for (const ExtensionFrameHelper
* helper
: g_frame_helpers
.Get()) {
71 if (RenderFrameMatches(helper
, view_type
, browser_window_id
, extension_id
))
72 render_frames
.push_back(helper
->render_frame());
78 content::RenderFrame
* ExtensionFrameHelper::GetBackgroundPageFrame(
79 const std::string
& extension_id
) {
80 for (const ExtensionFrameHelper
* helper
: g_frame_helpers
.Get()) {
81 if (RenderFrameMatches(helper
, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
,
82 extension_misc::kUnknownWindowId
, extension_id
)) {
83 blink::WebLocalFrame
* web_frame
= helper
->render_frame()->GetWebFrame();
84 // Check if this is the top frame.
85 if (web_frame
->top() == web_frame
)
86 return helper
->render_frame();
93 bool ExtensionFrameHelper::IsContextForEventPage(const ScriptContext
* context
) {
94 content::RenderFrame
* render_frame
= context
->GetRenderFrame();
95 return context
->extension() && render_frame
&&
96 BackgroundInfo::HasLazyBackgroundPage(context
->extension()) &&
97 ExtensionFrameHelper::Get(render_frame
)->view_type() ==
98 VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
;
101 void ExtensionFrameHelper::DidCreateScriptContext(
102 v8::Local
<v8::Context
> context
,
105 extension_dispatcher_
->DidCreateScriptContext(
106 render_frame()->GetWebFrame(), context
, extension_group
, world_id
);
109 void ExtensionFrameHelper::WillReleaseScriptContext(
110 v8::Local
<v8::Context
> context
,
112 extension_dispatcher_
->WillReleaseScriptContext(
113 render_frame()->GetWebFrame(), context
, world_id
);
116 bool ExtensionFrameHelper::OnMessageReceived(const IPC::Message
& message
) {
118 IPC_BEGIN_MESSAGE_MAP(ExtensionFrameHelper
, message
)
119 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect
,
120 OnExtensionDispatchOnConnect
)
121 IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage
, OnExtensionDeliverMessage
)
122 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect
,
123 OnExtensionDispatchOnDisconnect
)
124 IPC_MESSAGE_HANDLER(ExtensionMsg_SetTabId
, OnExtensionSetTabId
)
125 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateBrowserWindowId
,
126 OnUpdateBrowserWindowId
)
127 IPC_MESSAGE_HANDLER(ExtensionMsg_SetMainFrameExtensionOwner
,
128 OnSetMainFrameExtensionOwner
)
129 IPC_MESSAGE_HANDLER(ExtensionMsg_NotifyRenderViewType
,
130 OnNotifyRendererViewType
)
131 IPC_MESSAGE_HANDLER(ExtensionMsg_Response
, OnExtensionResponse
)
132 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke
, OnExtensionMessageInvoke
)
133 IPC_MESSAGE_UNHANDLED(handled
= false)
134 IPC_END_MESSAGE_MAP()
138 void ExtensionFrameHelper::OnExtensionDispatchOnConnect(
140 const std::string
& channel_name
,
141 const ExtensionMsg_TabConnectionInfo
& source
,
142 const ExtensionMsg_ExternalConnectionInfo
& info
,
143 const std::string
& tls_channel_id
) {
144 MessagingBindings::DispatchOnConnect(
145 extension_dispatcher_
->script_context_set(),
154 void ExtensionFrameHelper::OnExtensionDeliverMessage(int target_id
,
155 const Message
& message
) {
156 MessagingBindings::DeliverMessage(
157 extension_dispatcher_
->script_context_set(), target_id
, message
,
161 void ExtensionFrameHelper::OnExtensionDispatchOnDisconnect(
163 const std::string
& error_message
) {
164 MessagingBindings::DispatchOnDisconnect(
165 extension_dispatcher_
->script_context_set(), port_id
, error_message
,
169 void ExtensionFrameHelper::OnExtensionSetTabId(int tab_id
) {
170 CHECK_EQ(tab_id_
, -1);
175 void ExtensionFrameHelper::OnUpdateBrowserWindowId(int browser_window_id
) {
176 browser_window_id_
= browser_window_id
;
179 void ExtensionFrameHelper::OnSetMainFrameExtensionOwner(
180 const std::string
& extension_id
) {
181 tab_extension_owner_id_
= extension_id
;
184 void ExtensionFrameHelper::OnNotifyRendererViewType(ViewType type
) {
185 // TODO(devlin): It'd be really nice to be able to
186 // DCHECK_EQ(VIEW_TYPE_INVALID, view_type_) here.
190 void ExtensionFrameHelper::OnExtensionResponse(int request_id
,
192 const base::ListValue
& response
,
193 const std::string
& error
) {
194 extension_dispatcher_
->OnExtensionResponse(request_id
,
200 void ExtensionFrameHelper::OnExtensionMessageInvoke(
201 const std::string
& extension_id
,
202 const std::string
& module_name
,
203 const std::string
& function_name
,
204 const base::ListValue
& args
,
206 extension_dispatcher_
->InvokeModuleSystemMethod(render_frame(), extension_id
,
207 module_name
, function_name
,
211 } // namespace extensions