1 // Copyright 2014 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_helper.h"
7 #include "content/public/renderer/render_view.h"
8 #include "content/public/renderer/render_view_visitor.h"
9 #include "extensions/common/constants.h"
10 #include "extensions/common/extension_messages.h"
11 #include "extensions/common/permissions/permissions_data.h"
12 #include "extensions/common/url_pattern_set.h"
13 #include "extensions/renderer/api/automation/automation_api_helper.h"
14 #include "extensions/renderer/console.h"
15 #include "extensions/renderer/dispatcher.h"
16 #include "third_party/WebKit/public/platform/WebURLRequest.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"
20 #include "third_party/WebKit/public/web/WebView.h"
22 using content::ConsoleMessageLevel
;
23 using blink::WebConsoleMessage
;
24 using blink::WebDataSource
;
25 using blink::WebFrame
;
26 using blink::WebLocalFrame
;
27 using blink::WebURLRequest
;
30 namespace extensions
{
34 // A RenderViewVisitor class that iterates through the set of available
35 // views, looking for a view of the given type, in the given browser window
36 // and within the given extension.
37 // Used to accumulate the list of views associated with an extension.
38 class ViewAccumulator
: public content::RenderViewVisitor
{
40 ViewAccumulator(const std::string
& extension_id
,
41 int browser_window_id
,
43 : extension_id_(extension_id
),
44 browser_window_id_(browser_window_id
),
45 view_type_(view_type
) {
48 std::vector
<content::RenderView
*> views() { return views_
; }
50 // Returns false to terminate the iteration.
51 bool Visit(content::RenderView
* render_view
) override
{
52 ExtensionHelper
* helper
= ExtensionHelper::Get(render_view
);
53 if (!ViewTypeMatches(helper
->view_type(), view_type_
))
56 GURL url
= render_view
->GetWebView()->mainFrame()->document().url();
57 if (!url
.SchemeIs(kExtensionScheme
))
59 const std::string
& extension_id
= url
.host();
60 if (extension_id
!= extension_id_
)
63 if (browser_window_id_
!= extension_misc::kUnknownWindowId
&&
64 helper
->browser_window_id() != browser_window_id_
) {
68 views_
.push_back(render_view
);
70 if (view_type_
== VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
)
71 return false; // There can be only one...
76 // Returns true if |type| "isa" |match|.
77 static bool ViewTypeMatches(ViewType type
, ViewType match
) {
81 // INVALID means match all.
82 if (match
== VIEW_TYPE_INVALID
)
88 std::string extension_id_
;
89 int browser_window_id_
;
91 std::vector
<content::RenderView
*> views_
;
97 std::vector
<content::RenderView
*> ExtensionHelper::GetExtensionViews(
98 const std::string
& extension_id
,
99 int browser_window_id
,
100 ViewType view_type
) {
101 ViewAccumulator
accumulator(extension_id
, browser_window_id
, view_type
);
102 content::RenderView::ForEach(&accumulator
);
103 return accumulator
.views();
107 content::RenderView
* ExtensionHelper::GetBackgroundPage(
108 const std::string
& extension_id
) {
109 ViewAccumulator
accumulator(extension_id
, extension_misc::kUnknownWindowId
,
110 VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
);
111 content::RenderView::ForEach(&accumulator
);
112 CHECK_LE(accumulator
.views().size(), 1u);
113 if (accumulator
.views().size() == 0)
115 return accumulator
.views()[0];
118 ExtensionHelper::ExtensionHelper(content::RenderView
* render_view
,
119 Dispatcher
* dispatcher
)
120 : content::RenderViewObserver(render_view
),
121 content::RenderViewObserverTracker
<ExtensionHelper
>(render_view
),
122 dispatcher_(dispatcher
),
123 view_type_(VIEW_TYPE_INVALID
),
125 browser_window_id_(-1) {
126 // Lifecycle managed by RenderViewObserver.
127 new AutomationApiHelper(render_view
);
130 ExtensionHelper::~ExtensionHelper() {
133 bool ExtensionHelper::OnMessageReceived(const IPC::Message
& message
) {
135 IPC_BEGIN_MESSAGE_MAP(ExtensionHelper
, message
)
136 IPC_MESSAGE_HANDLER(ExtensionMsg_Response
, OnExtensionResponse
)
137 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke
, OnExtensionMessageInvoke
)
138 IPC_MESSAGE_HANDLER(ExtensionMsg_SetFrameName
, OnSetFrameName
)
139 IPC_MESSAGE_HANDLER(ExtensionMsg_SetTabId
, OnSetTabId
)
140 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateBrowserWindowId
,
141 OnUpdateBrowserWindowId
)
142 IPC_MESSAGE_HANDLER(ExtensionMsg_NotifyRenderViewType
,
143 OnNotifyRendererViewType
)
144 IPC_MESSAGE_HANDLER(ExtensionMsg_AddMessageToConsole
,
145 OnAddMessageToConsole
)
146 IPC_MESSAGE_HANDLER(ExtensionMsg_AppWindowClosed
,
148 IPC_MESSAGE_UNHANDLED(handled
= false)
149 IPC_END_MESSAGE_MAP()
153 void ExtensionHelper::DidCreateDocumentElement(WebLocalFrame
* frame
) {
154 dispatcher_
->DidCreateDocumentElement(frame
);
157 void ExtensionHelper::DraggableRegionsChanged(blink::WebFrame
* frame
) {
158 blink::WebVector
<blink::WebDraggableRegion
> webregions
=
159 frame
->document().draggableRegions();
160 std::vector
<DraggableRegion
> regions
;
161 for (size_t i
= 0; i
< webregions
.size(); ++i
) {
162 DraggableRegion region
;
163 region
.bounds
= webregions
[i
].bounds
;
164 region
.draggable
= webregions
[i
].draggable
;
165 regions
.push_back(region
);
167 Send(new ExtensionHostMsg_UpdateDraggableRegions(routing_id(), regions
));
170 void ExtensionHelper::DidMatchCSS(
171 blink::WebLocalFrame
* frame
,
172 const blink::WebVector
<blink::WebString
>& newly_matching_selectors
,
173 const blink::WebVector
<blink::WebString
>& stopped_matching_selectors
) {
174 dispatcher_
->DidMatchCSS(
175 frame
, newly_matching_selectors
, stopped_matching_selectors
);
178 void ExtensionHelper::OnExtensionResponse(int request_id
,
180 const base::ListValue
& response
,
181 const std::string
& error
) {
182 dispatcher_
->OnExtensionResponse(request_id
,
188 void ExtensionHelper::OnExtensionMessageInvoke(const std::string
& extension_id
,
189 const std::string
& module_name
,
190 const std::string
& function_name
,
191 const base::ListValue
& args
,
193 dispatcher_
->InvokeModuleSystemMethod(
194 render_view(), extension_id
, module_name
, function_name
, args
,
198 void ExtensionHelper::OnNotifyRendererViewType(ViewType type
) {
202 void ExtensionHelper::OnSetFrameName(const std::string
& name
) {
203 blink::WebView
* web_view
= render_view()->GetWebView();
205 web_view
->mainFrame()->setName(blink::WebString::fromUTF8(name
));
208 void ExtensionHelper::OnSetTabId(int init_tab_id
) {
209 CHECK_EQ(tab_id_
, -1);
210 CHECK_GE(init_tab_id
, 0);
211 tab_id_
= init_tab_id
;
214 void ExtensionHelper::OnUpdateBrowserWindowId(int window_id
) {
215 browser_window_id_
= window_id
;
218 void ExtensionHelper::OnAddMessageToConsole(ConsoleMessageLevel level
,
219 const std::string
& message
) {
220 console::AddMessage(render_view(), level
, message
);
223 void ExtensionHelper::OnAppWindowClosed() {
224 v8::HandleScope
scope(v8::Isolate::GetCurrent());
225 v8::Handle
<v8::Context
> v8_context
=
226 render_view()->GetWebView()->mainFrame()->mainWorldScriptContext();
227 ScriptContext
* script_context
=
228 dispatcher_
->script_context_set().GetByV8Context(v8_context
);
231 script_context
->module_system()->CallModuleMethod("app.window",
232 "onAppWindowClosed");
235 } // namespace extensions