Upstream version 9.38.198.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_SetTabId, OnSetTabId)
141     IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateBrowserWindowId,
142                         OnUpdateBrowserWindowId)
143     IPC_MESSAGE_HANDLER(ExtensionMsg_NotifyRenderViewType,
144                         OnNotifyRendererViewType)
145     IPC_MESSAGE_HANDLER(ExtensionMsg_AddMessageToConsole,
146                         OnAddMessageToConsole)
147     IPC_MESSAGE_HANDLER(ExtensionMsg_AppWindowClosed,
148                         OnAppWindowClosed)
149     IPC_MESSAGE_UNHANDLED(handled = false)
150   IPC_END_MESSAGE_MAP()
151   return handled;
152 }
153
154 void ExtensionHelper::DidCreateDocumentElement(WebLocalFrame* frame) {
155   dispatcher_->DidCreateDocumentElement(frame);
156 }
157
158 void ExtensionHelper::DraggableRegionsChanged(blink::WebFrame* frame) {
159   blink::WebVector<blink::WebDraggableRegion> webregions =
160       frame->document().draggableRegions();
161   std::vector<DraggableRegion> regions;
162   for (size_t i = 0; i < webregions.size(); ++i) {
163     DraggableRegion region;
164     region.bounds = webregions[i].bounds;
165     region.draggable = webregions[i].draggable;
166     regions.push_back(region);
167   }
168   Send(new ExtensionHostMsg_UpdateDraggableRegions(routing_id(), regions));
169 }
170
171 void ExtensionHelper::DidMatchCSS(
172     blink::WebLocalFrame* frame,
173     const blink::WebVector<blink::WebString>& newly_matching_selectors,
174     const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
175   dispatcher_->DidMatchCSS(
176       frame, newly_matching_selectors, stopped_matching_selectors);
177 }
178
179 void ExtensionHelper::OnExtensionResponse(int request_id,
180                                           bool success,
181                                           const base::ListValue& response,
182                                           const std::string& error) {
183   dispatcher_->OnExtensionResponse(request_id,
184                                    success,
185                                    response,
186                                    error);
187 }
188
189 void ExtensionHelper::OnExtensionMessageInvoke(const std::string& extension_id,
190                                                const std::string& module_name,
191                                                const std::string& function_name,
192                                                const base::ListValue& args,
193                                                bool user_gesture) {
194   dispatcher_->InvokeModuleSystemMethod(
195       render_view(), extension_id, module_name, function_name, args,
196       user_gesture);
197 }
198
199 void ExtensionHelper::OnExtensionDispatchOnConnect(
200     int target_port_id,
201     const std::string& channel_name,
202     const base::DictionaryValue& source_tab,
203     const ExtensionMsg_ExternalConnectionInfo& info,
204     const std::string& tls_channel_id) {
205   MessagingBindings::DispatchOnConnect(dispatcher_->script_context_set(),
206                                        target_port_id,
207                                        channel_name,
208                                        source_tab,
209                                        info,
210                                        tls_channel_id,
211                                        render_view());
212 }
213
214 void ExtensionHelper::OnExtensionDeliverMessage(int target_id,
215                                                 const Message& message) {
216   MessagingBindings::DeliverMessage(
217       dispatcher_->script_context_set(), target_id, message, render_view());
218 }
219
220 void ExtensionHelper::OnExtensionDispatchOnDisconnect(
221     int port_id,
222     const std::string& error_message) {
223   MessagingBindings::DispatchOnDisconnect(
224       dispatcher_->script_context_set(), port_id, error_message, render_view());
225 }
226
227 void ExtensionHelper::OnNotifyRendererViewType(ViewType type) {
228   view_type_ = type;
229 }
230
231 void ExtensionHelper::OnSetTabId(int init_tab_id) {
232   CHECK_EQ(tab_id_, -1);
233   CHECK_GE(init_tab_id, 0);
234   tab_id_ = init_tab_id;
235 }
236
237 void ExtensionHelper::OnUpdateBrowserWindowId(int window_id) {
238   browser_window_id_ = window_id;
239 }
240
241 void ExtensionHelper::OnAddMessageToConsole(ConsoleMessageLevel level,
242                                             const std::string& message) {
243   console::AddMessage(render_view(), level, message);
244 }
245
246 void ExtensionHelper::OnAppWindowClosed() {
247   v8::HandleScope scope(v8::Isolate::GetCurrent());
248   v8::Handle<v8::Context> v8_context =
249       render_view()->GetWebView()->mainFrame()->mainWorldScriptContext();
250   ScriptContext* script_context =
251       dispatcher_->script_context_set().GetByV8Context(v8_context);
252   if (!script_context)
253     return;
254   script_context->module_system()->CallModuleMethod("app.window",
255                                                     "onAppWindowClosed");
256 }
257
258 }  // namespace extensions