diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-16 02:08:42 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-16 02:08:42 +0000 |
commit | 38b592904f582daacd833b767b3cce3d1c211068 (patch) | |
tree | a91ae9b6694153f8f017778e56f67797fc2a136d /chrome/renderer/extensions | |
parent | 4766a6019405334b45222b48560aeda994a0e8e8 (diff) | |
download | chromium_src-38b592904f582daacd833b767b3cce3d1c211068.zip chromium_src-38b592904f582daacd833b767b3cce3d1c211068.tar.gz chromium_src-38b592904f582daacd833b767b3cce3d1c211068.tar.bz2 |
Clear RenderThread of any Chrome specific code, and move a bunch of stuff out of RenderView.
Took out CookieMessageFilter since it's not used anymore. Removed RenderProcessTest and RendererMainTest since they really weren't testing much.
Review URL: http://codereview.chromium.org/6873014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81851 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/extensions')
-rw-r--r-- | chrome/renderer/extensions/chrome_app_bindings.cc | 5 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_helper.cc | 194 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_helper.h | 46 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_process_bindings.cc | 13 | ||||
-rw-r--r-- | chrome/renderer/extensions/user_script_slave.cc | 7 |
5 files changed, 250 insertions, 15 deletions
diff --git a/chrome/renderer/extensions/chrome_app_bindings.cc b/chrome/renderer/extensions/chrome_app_bindings.cc index e71209d..aafa672 100644 --- a/chrome/renderer/extensions/chrome_app_bindings.cc +++ b/chrome/renderer/extensions/chrome_app_bindings.cc @@ -14,6 +14,7 @@ #include "chrome/common/extensions/extension_set.h" #include "chrome/renderer/extensions/bindings_utils.h" #include "chrome/renderer/extensions/extension_dispatcher.h" +#include "chrome/renderer/extensions/extension_helper.h" #include "content/renderer/render_view.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "v8/include/v8.h" @@ -123,7 +124,9 @@ class ChromeAppExtensionWrapper : public v8::Extension { RenderView* render_view = bindings_utils::GetRenderViewForCurrentContext(); if (frame && render_view) { string16 error; - if (!render_view->InstallWebApplicationUsingDefinitionFile(frame, &error)) + + ExtensionHelper* helper = ExtensionHelper::Get(render_view); + if (!helper->InstallWebApplicationUsingDefinitionFile(frame, &error)) v8::ThrowException(v8::String::New(UTF16ToUTF8(error).c_str())); } diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc index 4e3a9ef..f4d043e 100644 --- a/chrome/renderer/extensions/extension_helper.cc +++ b/chrome/renderer/extensions/extension_helper.cc @@ -4,20 +4,34 @@ #include "chrome/renderer/extensions/extension_helper.h" +#include "base/command_line.h" #include "base/lazy_instance.h" +#include "base/message_loop.h" +#include "base/utf_string_conversions.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_messages.h" +#include "chrome/common/json_value_serializer.h" +#include "chrome/common/url_constants.h" #include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/extensions/extension_process_bindings.h" #include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/extensions/user_script_idle_scheduler.h" #include "chrome/renderer/extensions/user_script_slave.h" #include "content/renderer/render_view.h" +#include "webkit/glue/image_resource_fetcher.h" +#include "webkit/glue/resource_fetcher.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" +using WebKit::WebConsoleMessage; using WebKit::WebDataSource; using WebKit::WebFrame; +using WebKit::WebURLRequest; using WebKit::WebView; +using webkit_glue::ImageResourceFetcher; +using webkit_glue::ResourceFetcher; namespace { // Keeps a mapping from the frame pointer to a UserScriptIdleScheduler object. @@ -31,18 +45,67 @@ static base::LazyInstance<SchedulerMap> g_schedulers(base::LINKER_INITIALIZED); ExtensionHelper::ExtensionHelper(RenderView* render_view, ExtensionDispatcher* extension_dispatcher) : RenderViewObserver(render_view), - extension_dispatcher_(extension_dispatcher) { + RenderViewObserverTracker<ExtensionHelper>(render_view), + extension_dispatcher_(extension_dispatcher), + pending_app_icon_requests_(0) { } ExtensionHelper::~ExtensionHelper() { } +bool ExtensionHelper::InstallWebApplicationUsingDefinitionFile( + WebFrame* frame, string16* error) { + // There is an issue of drive-by installs with the below implementation. A web + // site could force a user to install an app by timing the dialog to come up + // just before the user clicks. + // + // We do show a success UI that allows users to uninstall, but it seems that + // we might still want to put up an infobar before showing the install dialog. + // + // TODO(aa): Figure out this issue before removing the kEnableCrxlessWebApps + // switch. + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableCrxlessWebApps)) { + *error = ASCIIToUTF16("CRX-less web apps aren't enabled."); + return false; + } + + if (frame != frame->top()) { + *error = ASCIIToUTF16("Applications can only be installed from the top " + "frame."); + return false; + } + + if (pending_app_info_.get()) { + *error = ASCIIToUTF16("An application install is already in progress."); + return false; + } + + pending_app_info_.reset(new WebApplicationInfo()); + if (!web_apps::ParseWebAppFromWebDocument(frame, pending_app_info_.get(), + error)) { + return false; + } + + if (!pending_app_info_->manifest_url.is_valid()) { + *error = ASCIIToUTF16("Web application definition not found or invalid."); + return false; + } + + app_definition_fetcher_.reset(new ResourceFetcher( + pending_app_info_->manifest_url, render_view()->webview()->mainFrame(), + WebURLRequest::TargetIsSubresource, + NewCallback(this, &ExtensionHelper::DidDownloadApplicationDefinition))); + return true; +} + bool ExtensionHelper::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ExtensionHelper, message) IPC_MESSAGE_HANDLER(ExtensionMsg_Response, OnExtensionResponse) IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnExtensionMessageInvoke) IPC_MESSAGE_HANDLER(ExtensionMsg_ExecuteCode, OnExecuteCode) + IPC_MESSAGE_HANDLER(ExtensionMsg_GetApplicationInfo, OnGetApplicationInfo) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -86,6 +149,13 @@ void ExtensionHelper::FrameDetached(WebFrame* frame) { } void ExtensionHelper::DidCreateDataSource(WebFrame* frame, WebDataSource* ds) { + // If there are any app-related fetches in progress, they can be cancelled now + // since we have navigated away from the page that created them. + if (!frame->parent()) { + app_icon_fetchers_.clear(); + app_definition_fetcher_.reset(NULL); + } + // Check first if we created a scheduler for the frame, since this function // gets called for navigations within the document. if (g_schedulers.Get().count(frame)) @@ -127,3 +197,125 @@ void ExtensionHelper::OnExecuteCode( if (i != g_schedulers.Get().end()) i->second->ExecuteCode(params); } + +void ExtensionHelper::OnGetApplicationInfo(int page_id) { + WebApplicationInfo app_info; + if (page_id == render_view()->page_id()) { + string16 error; + web_apps::ParseWebAppFromWebDocument( + render_view()->webview()->mainFrame(), &app_info, &error); + } + + // Prune out any data URLs in the set of icons. The browser process expects + // any icon with a data URL to have originated from a favicon. We don't want + // to decode arbitrary data URLs in the browser process. See + // http://b/issue?id=1162972 + for (size_t i = 0; i < app_info.icons.size(); ++i) { + if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) { + app_info.icons.erase(app_info.icons.begin() + i); + --i; + } + } + + Send(new ExtensionHostMsg_DidGetApplicationInfo( + routing_id(), page_id, app_info)); +} + +void ExtensionHelper::DidDownloadApplicationDefinition( + const WebKit::WebURLResponse& response, + const std::string& data) { + scoped_ptr<WebApplicationInfo> app_info( + pending_app_info_.release()); + + JSONStringValueSerializer serializer(data); + int error_code = 0; + std::string error_message; + scoped_ptr<Value> result(serializer.Deserialize(&error_code, &error_message)); + if (!result.get()) { + AddErrorToRootConsole(UTF8ToUTF16(error_message)); + return; + } + + string16 error_message_16; + if (!web_apps::ParseWebAppFromDefinitionFile(result.get(), app_info.get(), + &error_message_16)) { + AddErrorToRootConsole(error_message_16); + return; + } + + if (!app_info->icons.empty()) { + pending_app_info_.reset(app_info.release()); + pending_app_icon_requests_ = + static_cast<int>(pending_app_info_->icons.size()); + for (size_t i = 0; i < pending_app_info_->icons.size(); ++i) { + app_icon_fetchers_.push_back(linked_ptr<ImageResourceFetcher>( + new ImageResourceFetcher( + pending_app_info_->icons[i].url, + render_view()->webview()->mainFrame(), + static_cast<int>(i), + pending_app_info_->icons[i].width, + WebURLRequest::TargetIsFavicon, + NewCallback( + this, &ExtensionHelper::DidDownloadApplicationIcon)))); + } + } else { + Send(new ExtensionHostMsg_InstallApplication(routing_id(), *app_info)); + } +} + +void ExtensionHelper::DidDownloadApplicationIcon(ImageResourceFetcher* fetcher, + const SkBitmap& image) { + pending_app_info_->icons[fetcher->id()].data = image; + + // Remove the image fetcher from our pending list. We're in the callback from + // ImageResourceFetcher, best to delay deletion. + RenderView::ImageResourceFetcherList::iterator i; + for (i = app_icon_fetchers_.begin(); i != app_icon_fetchers_.end(); ++i) { + if (i->get() == fetcher) { + i->release(); + app_icon_fetchers_.erase(i); + break; + } + } + + // We're in the callback from the ImageResourceFetcher, best to delay + // deletion. + MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher); + + if (--pending_app_icon_requests_ > 0) + return; + + // There is a maximum size of IPC on OS X and Linux that we have run into in + // some situations. We're not sure what it is, but our hypothesis is in the + // neighborhood of 1 MB. + // + // To be on the safe side, we give ourselves 128 KB for just the image data. + // This should be more than enough for 128, 48, and 16 px 32-bit icons. If we + // want to start allowing larger icons (see bug 63406), we'll have to either + // experiment mor ewith this and find the real limit, or else come up with + // some alternative way to transmit the icon data to the browser process. + // + // See also: bug 63729. + const size_t kMaxIconSize = 1024 * 128; + size_t actual_icon_size = 0; + for (size_t i = 0; i < pending_app_info_->icons.size(); ++i) { + size_t current_size = pending_app_info_->icons[i].data.getSize(); + if (current_size > kMaxIconSize - actual_icon_size) { + AddErrorToRootConsole(ASCIIToUTF16( + "Icons are too large. Maximum total size for app icons is 128 KB.")); + return; + } + actual_icon_size += current_size; + } + + Send(new ExtensionHostMsg_InstallApplication( + routing_id(), *pending_app_info_)); + pending_app_info_.reset(NULL); +} + +void ExtensionHelper::AddErrorToRootConsole(const string16& message) { + if (render_view()->webview() && render_view()->webview()->mainFrame()) { + render_view()->webview()->mainFrame()->addMessageToConsole( + WebConsoleMessage(WebConsoleMessage::LevelError, message)); + } +} diff --git a/chrome/renderer/extensions/extension_helper.h b/chrome/renderer/extensions/extension_helper.h index a51e1e7..2fc45ab 100644 --- a/chrome/renderer/extensions/extension_helper.h +++ b/chrome/renderer/extensions/extension_helper.h @@ -8,20 +8,35 @@ #include <map> +#include "content/renderer/render_view.h" #include "content/renderer/render_view_observer.h" +#include "content/renderer/render_view_observer_tracker.h" class ExtensionDispatcher; class GURL; class ListValue; struct ExtensionMsg_ExecuteCode_Params; +struct WebApplicationInfo; + +namespace webkit_glue { +class ResourceFetcher; +} // Filters extension related messages sent to RenderViews. -class ExtensionHelper : public RenderViewObserver { +class ExtensionHelper : public RenderViewObserver, + public RenderViewObserverTracker<ExtensionHelper> { public: ExtensionHelper(RenderView* render_view, ExtensionDispatcher* extension_dispatcher); virtual ~ExtensionHelper(); + // Starts installation of the page in the specified frame as a web app. The + // page must link to an external 'definition file'. This is different from + // the 'application shortcuts' feature where we pull the application + // definition out of optional meta tags in the page. + bool InstallWebApplicationUsingDefinitionFile(WebKit::WebFrame* frame, + string16* error); + private: // RenderViewObserver implementation. virtual bool OnMessageReceived(const IPC::Message& message); @@ -41,9 +56,38 @@ class ExtensionHelper : public RenderViewObserver { const ListValue& args, const GURL& event_url); void OnExecuteCode(const ExtensionMsg_ExecuteCode_Params& params); + void OnGetApplicationInfo(int page_id); + + // Callback triggered when we finish downloading the application definition + // file. + void DidDownloadApplicationDefinition(const WebKit::WebURLResponse& response, + const std::string& data); + + // Callback triggered after each icon referenced by the application definition + // is downloaded. + void DidDownloadApplicationIcon(webkit_glue::ImageResourceFetcher* fetcher, + const SkBitmap& image); + + // Helper to add an error message to the root frame's console. + void AddErrorToRootConsole(const string16& message); ExtensionDispatcher* extension_dispatcher_; + // The app info that we are processing. This is used when installing an app + // via application definition. The in-progress web app is stored here while + // its manifest and icons are downloaded. + scoped_ptr<WebApplicationInfo> pending_app_info_; + + // Used to download the application definition file. + scoped_ptr<webkit_glue::ResourceFetcher> app_definition_fetcher_; + + // Used to download the icons for an application. + RenderView::ImageResourceFetcherList app_icon_fetchers_; + + // The number of app icon requests outstanding. When this reaches zero, we're + // done processing an app definition file. + int pending_app_icon_requests_; + DISALLOW_COPY_AND_ASSIGN(ExtensionHelper); }; diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index 246f6ad..2e2bd78 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -22,13 +22,13 @@ #include "chrome/common/extensions/url_pattern.h" #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" +#include "chrome/renderer/chrome_render_process_observer.h" #include "chrome/renderer/extensions/bindings_utils.h" #include "chrome/renderer/extensions/event_bindings.h" #include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/extensions/js_only_v8_extensions.h" #include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/extensions/user_script_slave.h" -#include "content/renderer/render_thread.h" #include "content/renderer/render_view.h" #include "content/renderer/render_view_visitor.h" #include "grit/common_resources.h" @@ -530,17 +530,12 @@ class ExtensionImpl : public ExtensionBase { } static v8::Handle<v8::Value> IsExtensionProcess(const v8::Arguments& args) { - bool retval = false; - if (EventBindings::GetRenderThread()) - retval = extension_dispatcher_->is_extension_process(); - return v8::Boolean::New(retval); + return v8::Boolean::New(extension_dispatcher_->is_extension_process()); } static v8::Handle<v8::Value> IsIncognitoProcess(const v8::Arguments& args) { - bool retval = false; - if (EventBindings::GetRenderThread()) - retval = EventBindings::GetRenderThread()->IsIncognitoProcess(); - return v8::Boolean::New(retval); + return v8::Boolean::New( + ChromeRenderProcessObserver::is_incognito_process()); } static ExtensionDispatcher* extension_dispatcher_; diff --git a/chrome/renderer/extensions/user_script_slave.cc b/chrome/renderer/extensions/user_script_slave.cc index fa926d1..18a274f 100644 --- a/chrome/renderer/extensions/user_script_slave.cc +++ b/chrome/renderer/extensions/user_script_slave.cc @@ -16,8 +16,8 @@ #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_set.h" #include "chrome/common/url_constants.h" +#include "chrome/renderer/chrome_render_process_observer.h" #include "chrome/renderer/extension_groups.h" -#include "content/renderer/render_thread.h" #include "googleurl/src/gurl.h" #include "grit/renderer_resources.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" @@ -81,7 +81,8 @@ void UserScriptSlave::GetActiveExtensions( bool UserScriptSlave::UpdateScripts(base::SharedMemoryHandle shared_memory) { scripts_.clear(); - bool only_inject_incognito = RenderThread::current()->IsIncognitoProcess(); + bool only_inject_incognito = + ChromeRenderProcessObserver::is_incognito_process(); // Create the shared memory object (read only). shared_memory_.reset(new base::SharedMemory(shared_memory, true)); @@ -177,7 +178,7 @@ bool UserScriptSlave::UpdateScripts(base::SharedMemoryHandle shared_memory) { void UserScriptSlave::InsertInitExtensionCode( std::vector<WebScriptSource>* sources, const std::string& extension_id) { DCHECK(sources); - bool incognito = RenderThread::current()->IsIncognitoProcess(); + bool incognito = ChromeRenderProcessObserver::is_incognito_process(); sources->insert(sources->begin(), WebScriptSource(WebString::fromUTF8( StringPrintf(kInitExtension, extension_id.c_str(), incognito ? "true" : "false")))); |