Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(386)

Side by Side Diff: chrome/renderer/extensions/extension_helper.cc

Issue 6873014: Clear RenderThread of any Chrome specific code, and move a bunch of stuff out of RenderView. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/extensions/extension_helper.h" 5 #include "chrome/renderer/extensions/extension_helper.h"
6 6
7 #include "base/command_line.h"
7 #include "base/lazy_instance.h" 8 #include "base/lazy_instance.h"
9 #include "base/message_loop.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/common/chrome_switches.h"
8 #include "chrome/common/extensions/extension_messages.h" 12 #include "chrome/common/extensions/extension_messages.h"
13 #include "chrome/common/json_value_serializer.h"
14 #include "chrome/common/url_constants.h"
9 #include "chrome/renderer/extensions/extension_dispatcher.h" 15 #include "chrome/renderer/extensions/extension_dispatcher.h"
10 #include "chrome/renderer/extensions/extension_process_bindings.h" 16 #include "chrome/renderer/extensions/extension_process_bindings.h"
11 #include "chrome/renderer/extensions/renderer_extension_bindings.h" 17 #include "chrome/renderer/extensions/renderer_extension_bindings.h"
12 #include "chrome/renderer/extensions/user_script_idle_scheduler.h" 18 #include "chrome/renderer/extensions/user_script_idle_scheduler.h"
13 #include "chrome/renderer/extensions/user_script_slave.h" 19 #include "chrome/renderer/extensions/user_script_slave.h"
14 #include "content/renderer/render_view.h" 20 #include "content/renderer/render_view.h"
21 #include "webkit/glue/image_resource_fetcher.h"
22 #include "webkit/glue/resource_fetcher.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
17 27
28 using WebKit::WebConsoleMessage;
18 using WebKit::WebDataSource; 29 using WebKit::WebDataSource;
19 using WebKit::WebFrame; 30 using WebKit::WebFrame;
31 using WebKit::WebURLRequest;
20 using WebKit::WebView; 32 using WebKit::WebView;
33 using webkit_glue::ImageResourceFetcher;
34 using webkit_glue::ResourceFetcher;
21 35
22 namespace { 36 namespace {
23 // Keeps a mapping from the frame pointer to a UserScriptIdleScheduler object. 37 // Keeps a mapping from the frame pointer to a UserScriptIdleScheduler object.
24 // We store this mapping per process, because a frame can jump from one 38 // We store this mapping per process, because a frame can jump from one
25 // document to another with adoptNode, and so having the object be a 39 // document to another with adoptNode, and so having the object be a
26 // RenderViewObserver means it might miss some notifications after it moves. 40 // RenderViewObserver means it might miss some notifications after it moves.
27 typedef std::map<WebFrame*, UserScriptIdleScheduler*> SchedulerMap; 41 typedef std::map<WebFrame*, UserScriptIdleScheduler*> SchedulerMap;
28 static base::LazyInstance<SchedulerMap> g_schedulers(base::LINKER_INITIALIZED); 42 static base::LazyInstance<SchedulerMap> g_schedulers(base::LINKER_INITIALIZED);
29 } 43 }
30 44
31 ExtensionHelper::ExtensionHelper(RenderView* render_view, 45 ExtensionHelper::ExtensionHelper(RenderView* render_view,
32 ExtensionDispatcher* extension_dispatcher) 46 ExtensionDispatcher* extension_dispatcher)
33 : RenderViewObserver(render_view), 47 : RenderViewObserver(render_view),
34 extension_dispatcher_(extension_dispatcher) { 48 RenderViewObserverTracker<ExtensionHelper>(render_view),
49 extension_dispatcher_(extension_dispatcher),
50 pending_app_icon_requests_(0) {
35 } 51 }
36 52
37 ExtensionHelper::~ExtensionHelper() { 53 ExtensionHelper::~ExtensionHelper() {
38 } 54 }
39 55
56 bool ExtensionHelper::InstallWebApplicationUsingDefinitionFile(
57 WebFrame* frame, string16* error) {
58 // There is an issue of drive-by installs with the below implementation. A web
59 // site could force a user to install an app by timing the dialog to come up
60 // just before the user clicks.
61 //
62 // We do show a success UI that allows users to uninstall, but it seems that
63 // we might still want to put up an infobar before showing the install dialog.
64 //
65 // TODO(aa): Figure out this issue before removing the kEnableCrxlessWebApps
66 // switch.
67 if (!CommandLine::ForCurrentProcess()->HasSwitch(
68 switches::kEnableCrxlessWebApps)) {
69 *error = ASCIIToUTF16("CRX-less web apps aren't enabled.");
70 return false;
71 }
72
73 if (frame != frame->top()) {
74 *error = ASCIIToUTF16("Applications can only be installed from the top "
75 "frame.");
76 return false;
77 }
78
79 if (pending_app_info_.get()) {
80 *error = ASCIIToUTF16("An application install is already in progress.");
81 return false;
82 }
83
84 pending_app_info_.reset(new WebApplicationInfo());
85 if (!web_apps::ParseWebAppFromWebDocument(frame, pending_app_info_.get(),
86 error)) {
87 return false;
88 }
89
90 if (!pending_app_info_->manifest_url.is_valid()) {
91 *error = ASCIIToUTF16("Web application definition not found or invalid.");
92 return false;
93 }
94
95 app_definition_fetcher_.reset(new ResourceFetcher(
96 pending_app_info_->manifest_url, render_view()->webview()->mainFrame(),
97 WebURLRequest::TargetIsSubresource,
98 NewCallback(this, &ExtensionHelper::DidDownloadApplicationDefinition)));
99 return true;
100 }
101
40 bool ExtensionHelper::OnMessageReceived(const IPC::Message& message) { 102 bool ExtensionHelper::OnMessageReceived(const IPC::Message& message) {
41 bool handled = true; 103 bool handled = true;
42 IPC_BEGIN_MESSAGE_MAP(ExtensionHelper, message) 104 IPC_BEGIN_MESSAGE_MAP(ExtensionHelper, message)
43 IPC_MESSAGE_HANDLER(ExtensionMsg_Response, OnExtensionResponse) 105 IPC_MESSAGE_HANDLER(ExtensionMsg_Response, OnExtensionResponse)
44 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnExtensionMessageInvoke) 106 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnExtensionMessageInvoke)
45 IPC_MESSAGE_HANDLER(ExtensionMsg_ExecuteCode, OnExecuteCode) 107 IPC_MESSAGE_HANDLER(ExtensionMsg_ExecuteCode, OnExecuteCode)
108 IPC_MESSAGE_HANDLER(ExtensionMsg_GetApplicationInfo, OnGetApplicationInfo)
46 IPC_MESSAGE_UNHANDLED(handled = false) 109 IPC_MESSAGE_UNHANDLED(handled = false)
47 IPC_END_MESSAGE_MAP() 110 IPC_END_MESSAGE_MAP()
48 return handled; 111 return handled;
49 } 112 }
50 113
51 void ExtensionHelper::DidFinishDocumentLoad(WebFrame* frame) { 114 void ExtensionHelper::DidFinishDocumentLoad(WebFrame* frame) {
52 extension_dispatcher_->user_script_slave()->InjectScripts( 115 extension_dispatcher_->user_script_slave()->InjectScripts(
53 frame, UserScript::DOCUMENT_END); 116 frame, UserScript::DOCUMENT_END);
54 117
55 SchedulerMap::iterator i = g_schedulers.Get().find(frame); 118 SchedulerMap::iterator i = g_schedulers.Get().find(frame);
(...skipping 23 matching lines...) Expand all
79 // won't be in the map. 142 // won't be in the map.
80 SchedulerMap::iterator i = g_schedulers.Get().find(frame); 143 SchedulerMap::iterator i = g_schedulers.Get().find(frame);
81 if (i == g_schedulers.Get().end()) 144 if (i == g_schedulers.Get().end())
82 return; 145 return;
83 146
84 delete i->second; 147 delete i->second;
85 g_schedulers.Get().erase(i); 148 g_schedulers.Get().erase(i);
86 } 149 }
87 150
88 void ExtensionHelper::DidCreateDataSource(WebFrame* frame, WebDataSource* ds) { 151 void ExtensionHelper::DidCreateDataSource(WebFrame* frame, WebDataSource* ds) {
152 // If there are any app-related fetches in progress, they can be cancelled now
153 // since we have navigated away from the page that created them.
154 if (!frame->parent()) {
155 app_icon_fetchers_.clear();
156 app_definition_fetcher_.reset(NULL);
157 }
158
89 // Check first if we created a scheduler for the frame, since this function 159 // Check first if we created a scheduler for the frame, since this function
90 // gets called for navigations within the document. 160 // gets called for navigations within the document.
91 if (g_schedulers.Get().count(frame)) 161 if (g_schedulers.Get().count(frame))
92 return; 162 return;
93 163
94 g_schedulers.Get()[frame] = new UserScriptIdleScheduler( 164 g_schedulers.Get()[frame] = new UserScriptIdleScheduler(
95 frame, extension_dispatcher_); 165 frame, extension_dispatcher_);
96 } 166 }
97 167
98 void ExtensionHelper::OnExtensionResponse(int request_id, 168 void ExtensionHelper::OnExtensionResponse(int request_id,
(...skipping 21 matching lines...) Expand all
120 routing_id(), params.request_id, false, "")); 190 routing_id(), params.request_id, false, ""));
121 return; 191 return;
122 } 192 }
123 193
124 // chrome.tabs.executeScript() only supports execution in either the top frame 194 // chrome.tabs.executeScript() only supports execution in either the top frame
125 // or all frames. We handle both cases in the top frame. 195 // or all frames. We handle both cases in the top frame.
126 SchedulerMap::iterator i = g_schedulers.Get().find(main_frame); 196 SchedulerMap::iterator i = g_schedulers.Get().find(main_frame);
127 if (i != g_schedulers.Get().end()) 197 if (i != g_schedulers.Get().end())
128 i->second->ExecuteCode(params); 198 i->second->ExecuteCode(params);
129 } 199 }
200
201 void ExtensionHelper::OnGetApplicationInfo(int page_id) {
202 WebApplicationInfo app_info;
203 if (page_id == render_view()->page_id()) {
204 string16 error;
205 web_apps::ParseWebAppFromWebDocument(
206 render_view()->webview()->mainFrame(), &app_info, &error);
207 }
208
209 // Prune out any data URLs in the set of icons. The browser process expects
210 // any icon with a data URL to have originated from a favicon. We don't want
211 // to decode arbitrary data URLs in the browser process. See
212 // http://b/issue?id=1162972
213 for (size_t i = 0; i < app_info.icons.size(); ++i) {
214 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) {
215 app_info.icons.erase(app_info.icons.begin() + i);
216 --i;
217 }
218 }
219
220 Send(new ExtensionHostMsg_DidGetApplicationInfo(
221 routing_id(), page_id, app_info));
222 }
223
224 void ExtensionHelper::DidDownloadApplicationDefinition(
225 const WebKit::WebURLResponse& response,
226 const std::string& data) {
227 scoped_ptr<WebApplicationInfo> app_info(
228 pending_app_info_.release());
229
230 JSONStringValueSerializer serializer(data);
231 int error_code = 0;
232 std::string error_message;
233 scoped_ptr<Value> result(serializer.Deserialize(&error_code, &error_message));
234 if (!result.get()) {
235 AddErrorToRootConsole(UTF8ToUTF16(error_message));
236 return;
237 }
238
239 string16 error_message_16;
240 if (!web_apps::ParseWebAppFromDefinitionFile(result.get(), app_info.get(),
241 &error_message_16)) {
242 AddErrorToRootConsole(error_message_16);
243 return;
244 }
245
246 if (!app_info->icons.empty()) {
247 pending_app_info_.reset(app_info.release());
248 pending_app_icon_requests_ =
249 static_cast<int>(pending_app_info_->icons.size());
250 for (size_t i = 0; i < pending_app_info_->icons.size(); ++i) {
251 app_icon_fetchers_.push_back(linked_ptr<ImageResourceFetcher>(
252 new ImageResourceFetcher(
253 pending_app_info_->icons[i].url,
254 render_view()->webview()->mainFrame(),
255 static_cast<int>(i),
256 pending_app_info_->icons[i].width,
257 WebURLRequest::TargetIsFavicon,
258 NewCallback(
259 this, &ExtensionHelper::DidDownloadApplicationIcon))));
260 }
261 } else {
262 Send(new ExtensionHostMsg_InstallApplication(routing_id(), *app_info));
263 }
264 }
265
266 void ExtensionHelper::DidDownloadApplicationIcon(ImageResourceFetcher* fetcher,
267 const SkBitmap& image) {
268 pending_app_info_->icons[fetcher->id()].data = image;
269
270 // Remove the image fetcher from our pending list. We're in the callback from
271 // ImageResourceFetcher, best to delay deletion.
272 RenderView::ImageResourceFetcherList::iterator i;
273 for (i = app_icon_fetchers_.begin(); i != app_icon_fetchers_.end(); ++i) {
274 if (i->get() == fetcher) {
275 i->release();
276 app_icon_fetchers_.erase(i);
277 break;
278 }
279 }
280
281 // We're in the callback from the ImageResourceFetcher, best to delay
282 // deletion.
283 MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
284
285 if (--pending_app_icon_requests_ > 0)
286 return;
287
288 // There is a maximum size of IPC on OS X and Linux that we have run into in
289 // some situations. We're not sure what it is, but our hypothesis is in the
290 // neighborhood of 1 MB.
291 //
292 // To be on the safe side, we give ourselves 128 KB for just the image data.
293 // This should be more than enough for 128, 48, and 16 px 32-bit icons. If we
294 // want to start allowing larger icons (see bug 63406), we'll have to either
295 // experiment mor ewith this and find the real limit, or else come up with
296 // some alternative way to transmit the icon data to the browser process.
297 //
298 // See also: bug 63729.
299 const size_t kMaxIconSize = 1024 * 128;
300 size_t actual_icon_size = 0;
301 for (size_t i = 0; i < pending_app_info_->icons.size(); ++i) {
302 size_t current_size = pending_app_info_->icons[i].data.getSize();
303 if (current_size > kMaxIconSize - actual_icon_size) {
304 AddErrorToRootConsole(ASCIIToUTF16(
305 "Icons are too large. Maximum total size for app icons is 128 KB."));
306 return;
307 }
308 actual_icon_size += current_size;
309 }
310
311 Send(new ExtensionHostMsg_InstallApplication(
312 routing_id(), *pending_app_info_));
313 pending_app_info_.reset(NULL);
314 }
315
316 void ExtensionHelper::AddErrorToRootConsole(const string16& message) {
317 if (render_view()->webview() && render_view()->webview()->mainFrame()) {
318 render_view()->webview()->mainFrame()->addMessageToConsole(
319 WebConsoleMessage(WebConsoleMessage::LevelError, message));
320 }
321 }
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/extension_helper.h ('k') | chrome/renderer/extensions/extension_process_bindings.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698