diff options
author | aa@google.com <aa@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-16 23:57:47 +0000 |
---|---|---|
committer | aa@google.com <aa@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-16 23:57:47 +0000 |
commit | 1e0f70402b410a9e274e8d23eeab236b43810a00 (patch) | |
tree | 43ebd89055f4666ab3104554551a2177413382db /chrome/renderer | |
parent | c2dacc9ec41232903ba700c6aef5ef98bfcb8af8 (diff) | |
download | chromium_src-1e0f70402b410a9e274e8d23eeab236b43810a00.zip chromium_src-1e0f70402b410a9e274e8d23eeab236b43810a00.tar.gz chromium_src-1e0f70402b410a9e274e8d23eeab236b43810a00.tar.bz2 |
Adds a bit of Greasemonkey support hidden behind the --enable-greasemonkey flag. Implementation follows the pattern of the visited links system.
Things still to be done:
- stop using a hardcoded script directory
- watch script directory and update shared memory when necessary
- move file io to background thread
- support for @include patterns -- now, all scripts are applied to all pages
Review URL: http://codereview.chromium.org/7254
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3496 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/greasemonkey_slave.cc | 66 | ||||
-rw-r--r-- | chrome/renderer/greasemonkey_slave.h | 62 | ||||
-rw-r--r-- | chrome/renderer/render_thread.cc | 15 | ||||
-rw-r--r-- | chrome/renderer/render_thread.h | 7 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 17 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 3 | ||||
-rw-r--r-- | chrome/renderer/renderer.vcproj | 8 |
7 files changed, 175 insertions, 3 deletions
diff --git a/chrome/renderer/greasemonkey_slave.cc b/chrome/renderer/greasemonkey_slave.cc new file mode 100644 index 0000000..7a23017 --- /dev/null +++ b/chrome/renderer/greasemonkey_slave.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/greasemonkey_slave.h" + +#include "base/logging.h" +#include "base/pickle.h" +#include "base/shared_memory.h" + +GreasemonkeySlave::GreasemonkeySlave() : shared_memory_(NULL) { +} + +bool GreasemonkeySlave::UpdateScripts(SharedMemoryHandle shared_memory) { + scripts_.clear(); + + // Create the shared memory object. + shared_memory_.reset(new SharedMemory(shared_memory, true)); // read-only + if (!shared_memory_.get()) + return false; + + // First get the size of the memory block. + if (!shared_memory_->Map(sizeof(Pickle::Header))) + return false; + Pickle::Header* pickle_header = + reinterpret_cast<Pickle::Header*>(shared_memory_->memory()); + + // Now map in the rest of the block. + int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size; + shared_memory_->Unmap(); + if (!shared_memory_->Map(pickle_size)) + return false; + + // Unpickle scripts. + void* iter = NULL; + int num_scripts = 0; + Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), + pickle_size); + pickle.ReadInt(&iter, &num_scripts); + + for (int i = 0; i < num_scripts; ++i) { + const char* data = NULL; + int data_length = 0; + pickle.ReadData(&iter, &data, &data_length); + + GreasemonkeyScript script; + if (script.Parse(StringPiece(data, data_length))) { + scripts_.push_back(script); + } + } + + return true; +} + +bool GreasemonkeySlave::InjectScripts(WebFrame* frame) { + // TODO(aa): Check script patterns here + + for (std::vector<GreasemonkeyScript>::iterator script = scripts_.begin(); + script != scripts_.end(); ++script) { + // TODO(aa): Pass in URL to script when we have it. + frame->ExecuteJavaScript(script->GetBody().as_string(), + "Greasemonkey Script"); + } + + return true; +} diff --git a/chrome/renderer/greasemonkey_slave.h b/chrome/renderer/greasemonkey_slave.h new file mode 100644 index 0000000..7f35cec --- /dev/null +++ b/chrome/renderer/greasemonkey_slave.h @@ -0,0 +1,62 @@ +// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_GREASEMONKEY_SLAVE_H__ +#define CHROME_RENDERER_GREASEMONKEY_SLAVE_H__ + +#include <vector> + +#include "base/scoped_ptr.h" +#include "base/shared_memory.h" +#include "base/string_piece.h" +#include "webkit/glue/webframe.h" + +// Parsed representation of a Greasemonkey script. +class GreasemonkeyScript { + public: + // TODO(aa): Pass in filename script came from, for errors. Needs to be in + // shared memory. + GreasemonkeyScript() {} + + const StringPiece& GetBody() const { + return body_; + } + + bool Parse(const StringPiece& script_text) { + // TODO(aa): Parse out includes, convert to regexes. + body_ = script_text; + return true; + } + + private: + // References the body of the script in shared memory. The underlying memory + // is valid until shared_memory_ is either deleted or Unmap()'d. + StringPiece body_; +}; + + +// Manages installed GreasemonkeyScripts for a render process. +class GreasemonkeySlave { + public: + GreasemonkeySlave(); + + // Update the parsed scripts from shared memory. + bool UpdateScripts(SharedMemoryHandle shared_memory); + + // Inject the appropriate scripts into a frame based on its URL. + // TODO(aa): Extract a GreasemonkeyFrame interface out of this to improve + // testability. + bool InjectScripts(WebFrame* frame); + + private: + // Shared memory containing raw script data. + scoped_ptr<SharedMemory> shared_memory_; + + // Parsed script data. + std::vector<GreasemonkeyScript> scripts_; + + DISALLOW_COPY_AND_ASSIGN(GreasemonkeySlave); +}; + +#endif // CHROME_RENDERER_GREASEMONKEY_SLAVE_H__ diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index c389860..56ed3a8 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -15,6 +15,7 @@ #include "chrome/common/notification_service.h" #include "chrome/plugin/plugin_channel.h" #include "chrome/renderer/net/render_dns_master.h" +#include "chrome/renderer/greasemonkey_slave.h" #include "chrome/renderer/render_process.h" #include "chrome/renderer/render_view.h" #include "chrome/renderer/visitedlink_slave.h" @@ -41,6 +42,7 @@ RenderThread::RenderThread(const std::wstring& channel_name) channel_name_(channel_name), owner_loop_(MessageLoop::current()), visited_link_slave_(NULL), + greasemonkey_slave_(NULL), render_dns_master_(NULL), in_send_(0) { DCHECK(owner_loop_); @@ -111,9 +113,8 @@ void RenderThread::Init() { // The renderer thread should wind-up COM. CoInitialize(0); - // TODO(darin): We should actually try to share this object between - // RenderThread instances. visited_link_slave_ = new VisitedLinkSlave(); + greasemonkey_slave_ = new GreasemonkeySlave(); render_dns_master_.reset(new RenderDnsMaster()); @@ -141,6 +142,9 @@ void RenderThread::CleanUp() { delete visited_link_slave_; visited_link_slave_ = NULL; + delete greasemonkey_slave_; + greasemonkey_slave_ = NULL; + CoUninitialize(); } @@ -149,6 +153,11 @@ void RenderThread::OnUpdateVisitedLinks(SharedMemoryHandle table) { visited_link_slave_->Init(table); } +void RenderThread::OnUpdateGreasemonkeyScripts(SharedMemoryHandle scripts) { + DCHECK(scripts) << "Bad scripts handle"; + greasemonkey_slave_->UpdateScripts(scripts); +} + void RenderThread::OnMessageReceived(const IPC::Message& msg) { // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but // it seems simpler to just process any control messages that we care about @@ -163,6 +172,8 @@ void RenderThread::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats, OnGetCacheResourceStats) IPC_MESSAGE_HANDLER(ViewMsg_PluginMessage, OnPluginMessage) + IPC_MESSAGE_HANDLER(ViewMsg_Greasemonkey_NewScripts, + OnUpdateGreasemonkeyScripts) // send the rest to the router IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg)) IPC_END_MESSAGE_MAP() diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index 2d1c198..38fd144 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -18,6 +18,7 @@ class VisitedLinkSlave; struct WebPreferences; class RenderDnsMaster; class NotificationService; +class GreasemonkeySlave; // The RenderThreadBase is the minimal interface that a RenderWidget expects // from a render thread. The interface basically abstracts a way to send and @@ -64,8 +65,12 @@ class RenderThread : public IPC::Channel::Listener, // The RenderThread instance for the current thread. static RenderThread* current(); + // Gets the VisitedLinkSlave instance for this thread VisitedLinkSlave* visited_link_slave() const { return visited_link_slave_; } + // Gets the GreasemonkeySlave instance for this thread + GreasemonkeySlave* greasemonkey_slave() const { return greasemonkey_slave_; } + // Do DNS prefetch resolution of a hostname. void Resolve(const char* name, size_t length); @@ -89,6 +94,7 @@ class RenderThread : public IPC::Channel::Listener, private: void OnUpdateVisitedLinks(SharedMemoryHandle table); + void OnUpdateGreasemonkeyScripts(SharedMemoryHandle table); void OnPluginMessage(const std::wstring& dll_path, const std::vector<uint8>& data); @@ -120,6 +126,7 @@ class RenderThread : public IPC::Channel::Listener, // These objects live solely on the render thread. VisitedLinkSlave* visited_link_slave_; + GreasemonkeySlave* greasemonkey_slave_; scoped_ptr<RenderDnsMaster> render_dns_master_; diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index ef69bb6..528120b 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -31,6 +31,7 @@ #include "chrome/renderer/about_handler.h" #include "chrome/renderer/chrome_plugin_host.h" #include "chrome/renderer/debug_message_handler.h" +#include "chrome/renderer/greasemonkey_slave.h" #include "chrome/renderer/localized_error.h" #include "chrome/renderer/renderer_resources.h" #include "chrome/renderer/visitedlink_slave.h" @@ -150,7 +151,8 @@ RenderView::RenderView() history_back_list_count_(0), history_forward_list_count_(0), disable_popup_blocking_(false), - has_unload_listener_(false) { + has_unload_listener_(false), + greasemonkey_enabled_(false) { resource_dispatcher_ = new ResourceDispatcher(this); #ifdef CHROME_PERSONALIZATION personalization_ = Personalization::CreateRendererPersonalization(); @@ -261,6 +263,8 @@ void RenderView::Init(HWND parent_hwnd, command_line.HasSwitch(switches::kDomAutomationController); disable_popup_blocking_ = command_line.HasSwitch(switches::kDisablePopupBlocking); + greasemonkey_enabled_ = + command_line.HasSwitch(switches::kEnableGreasemonkey); debug_message_handler_ = new DebugMessageHandler(this); RenderThread::current()->AddFilter(debug_message_handler_); @@ -1369,6 +1373,17 @@ void RenderView::DidFinishDocumentLoadForFrame(WebView* webview, WebFrame* frame) { // Check whether we have new encoding name. UpdateEncoding(frame, webview->GetMainFrameEncodingName()); + + // Inject any Greasemonkey scripts. Do not inject into chrome UI pages, but + // do inject into any other document. + if (greasemonkey_enabled_) { + const GURL &gurl = frame->GetURL(); + if (gurl.SchemeIs("file") || + gurl.SchemeIs("http") || + gurl.SchemeIs("https")) { + RenderThread::current()->greasemonkey_slave()->InjectScripts(frame); + } + } } void RenderView::DidHandleOnloadEventsForFrame(WebView* webview, diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index a59f328..d307e48 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -623,6 +623,9 @@ class RenderView : public RenderWidget, public WebViewDelegate, // maintains the cache and other features of the accessibility tree. scoped_ptr<GlueAccessibility> glue_accessibility_; + // True if Greasemonkey is enabled in this process. + bool greasemonkey_enabled_; + DISALLOW_COPY_AND_ASSIGN(RenderView); }; diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj index 9d82fecb..2fa8d0c 100644 --- a/chrome/renderer/renderer.vcproj +++ b/chrome/renderer/renderer.vcproj @@ -202,6 +202,14 @@ > </File> <File + RelativePath=".\greasemonkey_slave.cc" + > + </File> + <File + RelativePath=".\greasemonkey_slave.h" + > + </File> + <File RelativePath=".\localized_error.cc" > </File> |