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 266