Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / extensions / renderer / extension_helper.cc
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.
4
5 #include "extensions/renderer/extension_helper.h"
6
7 #include "content/public/renderer/render_view.h"
8 #include "content/public/renderer/render_view_visitor.h"
9 #include "extensions/common/api/messaging/message.h"
10 #include "extensions/common/constants.h"
11 #include "extensions/common/extension_messages.h"
12 #include "extensions/renderer/console.h"
13 #include "extensions/renderer/dispatcher.h"
14 #include "extensions/renderer/messaging_bindings.h"
15 #include "third_party/WebKit/public/platform/WebURLRequest.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"
19 #include "third_party/WebKit/public/web/WebView.h"
20
21 using content::ConsoleMessageLevel;
22 using blink::WebConsoleMessage;
23 using blink::WebDataSource;
24 using blink::WebFrame;
25 using blink::WebLocalFrame;
26 using blink::WebURLRequest;
27 using blink::WebView;
28
29 namespace extensions {
30
31 namespace {
32
33 // A RenderViewVisitor class that iterates through the set of available
34 // views, looking for a view of the given type, in the given browser window
35 // and within the given extension.
36 // Used to accumulate the list of views associated with an extension.
37 class ViewAccumulator : public content::RenderViewVisitor {
38  public:
39   ViewAccumulator(const std::string& extension_id,
40                   int browser_window_id,
41                   ViewType view_type)
42       : extension_id_(extension_id),
43         browser_window_id_(browser_window_id),
44         view_type_(view_type) {
45   }
46
47   std::vector<content::RenderView*> views() { return views_; }
48
49   // Returns false to terminate the iteration.
50   virtual bool Visit(content::RenderView* render_view) OVERRIDE {
51     ExtensionHelper* helper = ExtensionHelper::Get(render_view);
52     if (!ViewTypeMatches(helper->view_type(), view_type_))
53       return true;
54
55     GURL url = render_view->GetWebView()->mainFrame()->document().url();
56     if (!url.SchemeIs(kExtensionScheme))
57       return true;
58     const std::string& extension_id = url.host();
59     if (extension_id != extension_id_)
60       return true;
61
62     if (browser_window_id_ != extension_misc::kUnknownWindowId &&
63         helper->browser_window_id() != browser_window_id_) {
64       return true;
65     }
66
67     views_.push_back(render_view);
68
69     if (view_type_ == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE)
70       return false;  // There can be only one...
71     return true;
72   }
73
74  private:
75   // Returns true if |type| "isa" |match|.
76   static bool ViewTypeMatches(ViewType type, ViewType match) {
77     if (type == match)
78       return true;
79
80     // INVALID means match all.
81     if (match == VIEW_TYPE_INVALID)
82       return true;
83
84     return false;
85   }
86
87   std::string extension_id_;
88   int browser_window_id_;
89   ViewType view_type_;
90   std::vector<content::RenderView*> views_;
91 };
92
93 }  // namespace
94
95 // static
96 std::vector<content::RenderView*> ExtensionHelper::GetExtensionViews(
97     const std::string& extension_id,
98     int browser_window_id,
99     ViewType view_type) {
100   ViewAccumulator accumulator(extension_id, browser_window_id, view_type);
101   content::RenderView::ForEach(&accumulator);
102   return accumulator.views();
103 }
104
105 // static
106 content::RenderView* ExtensionHelper::GetBackgroundPage(
107     const std::string& extension_id) {
108   ViewAccumulator accumulator(extension_id, extension_misc::kUnknownWindowId,
109                               VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
110   content::RenderView::ForEach(&accumulator);
111   CHECK_LE(accumulator.views().size(), 1u);
112   if (accumulator.views().size() == 0)
113     return NULL;
114   return accumulator.views()[0];
115 }
116
117 ExtensionHelper::ExtensionHelper(content::RenderView* render_view,
118                                  Dispatcher* dispatcher)
119     : content::RenderViewObserver(render_view),
120       content::RenderViewObserverTracker<ExtensionHelper>(render_view),
121       dispatcher_(dispatcher),
122       view_type_(VIEW_TYPE_INVALID),
123       tab_id_(-1),
124       browser_window_id_(-1) {
125 }
126
127 ExtensionHelper::~ExtensionHelper() {
128 }
129
130 bool ExtensionHelper::OnMessageReceived(const IPC::Message& message) {
131   bool handled = true;
132   IPC_BEGIN_MESSAGE_MAP(ExtensionHelper, message)
133     IPC_MESSAGE_HANDLER(ExtensionMsg_Response, OnExtensionResponse)
134     IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnExtensionMessageInvoke)
135     IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect,
136                         OnExtensionDispatchOnConnect)
137     IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnExtensionDeliverMessage)
138     IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect,
139                         OnExtensionDispatchOnDisconnect)
140     IPC_MESSAGE_HANDLER(ExtensionMsg_SetFrameName, OnSetFrameName)
141     IPC_MESSAGE_HANDLER(ExtensionMsg_SetTabId, OnSetTabId)
142     IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateBrowserWindowId,
143                         OnUpdateBrowserWindowId)
144     IPC_MESSAGE_HANDLER(ExtensionMsg_NotifyRenderViewType,
145                         OnNotifyRendererViewType)
146     IPC_MESSAGE_HANDLER(ExtensionMsg_AddMessageToConsole,
147                         OnAddMessageToConsole)
148     IPC_MESSAGE_HANDLER(ExtensionMsg_AppWindowClosed,
149                         OnAppWindowClosed)
150     IPC_MESSAGE_UNHANDLED(handled = false)
151   IPC_END_MESSAGE_MAP()
152   return handled;
153 }
154
155 void ExtensionHelper::DidCreateDocumentElement(WebLocalFrame* frame) {
156   dispatcher_->DidCreateDocumentElement(frame);
157 }
158
159 void ExtensionHelper::DraggableRegionsChanged(blink::WebFrame* frame) {
160   blink::WebVector<blink::WebDraggableRegion> webregions =
161       frame->document().draggableRegions();
162   std::vector<DraggableRegion> regions;
163   for (size_t i = 0; i < webregions.size(); ++i) {
164     DraggableRegion region;
165     region.bounds = webregions[i].bounds;
166     region.draggable = webregions[i].draggable;
167     regions.push_back(region);
168   }
169   Send(new ExtensionHostMsg_UpdateDraggableRegions(routing_id(), regions));
170 }
171
172 void ExtensionHelper::DidMatchCSS(
173     blink::WebLocalFrame* frame,
174     const blink::WebVector<blink::WebString>& newly_matching_selectors,
175     const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
176   dispatcher_->DidMatchCSS(
177       frame, newly_matching_selectors, stopped_matching_selectors);
178 }
179
180 void ExtensionHelper::OnExtensionResponse(int request_id,
181                                           bool success,
182                                           const base::ListValue& response,
183                                           const std::string& error) {
184   dispatcher_->OnExtensionResponse(request_id,
185                                    success,
186                                    response,
187                                    error);
188 }
189
190 void ExtensionHelper::OnExtensionMessageInvoke(const std::string& extension_id,
191                                                const std::string& module_name,
192                                                const std::string& function_name,
193                                                const base::ListValue& args,
194                                                bool user_gesture) {
195   dispatcher_->InvokeModuleSystemMethod(
196       render_view(), extension_id, module_name, function_name, args,
197       user_gesture);
198 }
199
200 void ExtensionHelper::OnExtensionDispatchOnConnect(
201     int target_port_id,
202     const std::string& channel_name,
203     const base::DictionaryValue& source_tab,
204     const ExtensionMsg_ExternalConnectionInfo& info,
205     const std::string& tls_channel_id) {
206   MessagingBindings::DispatchOnConnect(dispatcher_->script_context_set(),
207                                        target_port_id,
208                                        channel_name,
209                                        source_tab,
210                                        info,
211                                        tls_channel_id,
212                                        render_view());
213 }
214
215 void ExtensionHelper::OnExtensionDeliverMessage(int target_id,
216                                                 const Message& message) {
217   MessagingBindings::DeliverMessage(
218       dispatcher_->script_context_set(), target_id, message, render_view());
219 }
220
221 void ExtensionHelper::OnExtensionDispatchOnDisconnect(
222     int port_id,
223     const std::string& error_message) {
224   MessagingBindings::DispatchOnDisconnect(
225       dispatcher_->script_context_set(), port_id, error_message, render_view());
226 }
227
228 void ExtensionHelper::OnNotifyRendererViewType(ViewType type) {
229   view_type_ = type;
230 }
231
232 void ExtensionHelper::OnSetFrameName(const std::string& name) {
233   blink::WebView* web_view = render_view()->GetWebView();
234   if (web_view)
235     web_view->mainFrame()->setName(blink::WebString::fromUTF8(name));
236 }
237
238 void ExtensionHelper::OnSetTabId(int init_tab_id) {
239   CHECK_EQ(tab_id_, -1);
240   CHECK_GE(init_tab_id, 0);
241   tab_id_ = init_tab_id;
242 }
243
244 void ExtensionHelper::OnUpdateBrowserWindowId(int window_id) {
245   browser_window_id_ = window_id;
246 }
247
248 void ExtensionHelper::OnAddMessageToConsole(ConsoleMessageLevel level,
249                                             const std::string& message) {
250   console::AddMessage(render_view(), level, message);
251 }
252
253 void ExtensionHelper::OnAppWindowClosed() {
254   v8::HandleScope scope(v8::Isolate::GetCurrent());
255   v8::Handle<v8::Context> v8_context =
256       render_view()->GetWebView()->mainFrame()->mainWorldScriptContext();
257   ScriptContext* script_context =
258       dispatcher_->script_context_set().GetByV8Context(v8_context);
259   if (!script_context)
260     return;
261   script_context->module_system()->CallModuleMethod("app.window",
262                                                     "onAppWindowClosed");
263 }
264
265 }  // namespace extensions