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 | |
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
-rw-r--r-- | chrome/browser/browser.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/greasemonkey_master.cc | 73 | ||||
-rw-r--r-- | chrome/browser/greasemonkey_master.h | 47 | ||||
-rw-r--r-- | chrome/browser/render_process_host.cc | 70 | ||||
-rw-r--r-- | chrome/common/chrome_paths.cc | 5 | ||||
-rw-r--r-- | chrome/common/chrome_paths.h | 1 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 2 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 5 | ||||
-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 | ||||
-rw-r--r-- | webkit/glue/webframe.h | 6 | ||||
-rw-r--r-- | webkit/glue/webframe_impl.cc | 7 | ||||
-rw-r--r-- | webkit/glue/webframe_impl.h | 2 |
19 files changed, 389 insertions, 18 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index be4e198..743e775 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -2143,6 +2143,14 @@ > </File> <File + RelativePath=".\greasemonkey_master.cc" + > + </File> + <File + RelativePath=".\greasemonkey_master.h" + > + </File> + <File RelativePath=".\interstitial_page.cc" > </File> diff --git a/chrome/browser/greasemonkey_master.cc b/chrome/browser/greasemonkey_master.cc new file mode 100644 index 0000000..829b47b --- /dev/null +++ b/chrome/browser/greasemonkey_master.cc @@ -0,0 +1,73 @@ +// 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/browser/greasemonkey_master.h" + +#include "base/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/pickle.h" +#include "base/string_util.h" +#include "chrome/common/chrome_paths.h" + +bool GreasemonkeyMaster::UpdateScripts() { + std::vector<std::string> scripts; + std::wstring path; + + PathService::Get(chrome::DIR_USER_SCRIPTS, &path); + file_util::FileEnumerator enumerator(path, false, + file_util::FileEnumerator::FILES, + L"*.user.js"); + for (std::wstring file = enumerator.Next(); !file.empty(); + file = enumerator.Next()) { + // TODO(aa): Support unicode script files. + std::string contents; + file_util::ReadFileToString(file, &contents); + scripts.push_back(contents); + } + + // Pickle scripts data. + Pickle pickle; + pickle.WriteSize(scripts.size()); + for (std::vector<std::string>::iterator script = scripts.begin(); + script != scripts.end(); ++script) { + // Write script body as 'data' so that we can read it out in the slave + // without allocating a new string. + pickle.WriteData(script->c_str(), script->size()); + } + + // Create the shared memory object. + scoped_ptr<SharedMemory> temp_shared_memory(new SharedMemory()); + if (!temp_shared_memory.get()) { + return false; + } + + shared_memory_serial_++; + if (!temp_shared_memory->Create(std::wstring(), // anonymous + false, // read-only + false, // open existing + pickle.size())) { + return false; + } + + // Map into our process. + if (!temp_shared_memory->Map(pickle.size())) { + return false; + } + + // Copy the pickle to shared memory. + memcpy(temp_shared_memory->memory(), pickle.data(), pickle.size()); + + shared_memory_.reset(temp_shared_memory.release()); + return true; +} + +bool GreasemonkeyMaster::ShareToProcess(ProcessHandle process, + SharedMemoryHandle* new_handle) { + if (shared_memory_.get()) + return shared_memory_->ShareToProcess(process, new_handle); + + NOTREACHED(); + return false; +} diff --git a/chrome/browser/greasemonkey_master.h b/chrome/browser/greasemonkey_master.h new file mode 100644 index 0000000..6dcbc6e --- /dev/null +++ b/chrome/browser/greasemonkey_master.h @@ -0,0 +1,47 @@ +// 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_BROWSER_GREASEMONKEY_MASTER_H__ +#define CHROME_BROWSER_GREASEMONKEY_MASTER_H__ + +#include <vector> + +#include "base/process.h" +#include "base/scoped_ptr.h" +#include "base/shared_memory.h" + +// Manages a segment of shared memory that contains the Greasemonkey scripts the +// user has installed. +class GreasemonkeyMaster { + public: + GreasemonkeyMaster() + : shared_memory_serial_(0) {} + + // Reloads scripts from disk into a new chunk of shared memory and notifies + // renderers. + bool UpdateScripts(); + + // Creates a handle to the shared memory that can be used in the specified + // process. + bool ShareToProcess(ProcessHandle process, SharedMemoryHandle* new_handle); + + // Gets the segment of shared memory for the scripts. + SharedMemory* GetSharedMemory() const { + return shared_memory_.get(); + } + + private: + // Contains the scripts that were found the last time UpdateScripts() was + // called. + scoped_ptr<SharedMemory> shared_memory_; + + // A counter that is incremented each time a new shared memory segment is + // created. This is used to uniquely identify segments created at different + // times by this class. + int shared_memory_serial_; + + DISALLOW_COPY_AND_ASSIGN(GreasemonkeyMaster); +}; + +#endif // CHROME_BROWSER_GREASEMONKEY_MASTER_H__ diff --git a/chrome/browser/render_process_host.cc b/chrome/browser/render_process_host.cc index bcf5d72..62a73ee 100644 --- a/chrome/browser/render_process_host.cc +++ b/chrome/browser/render_process_host.cc @@ -21,6 +21,7 @@ #include "base/process_util.h" #include "base/rand_util.h" #include "base/shared_memory.h" +#include "base/singleton.h" #include "base/string_util.h" #include "base/sys_info.h" #include "base/thread.h" @@ -38,6 +39,7 @@ #include "chrome/browser/sandbox_policy.h" #include "chrome/browser/spellchecker.h" #include "chrome/browser/visitedlink_master.h" +#include "chrome/browser/greasemonkey_master.h" #include "chrome/browser/web_contents.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" @@ -268,6 +270,7 @@ bool RenderProcessHost::Init() { switches::kDisablePopupBlocking, switches::kUseLowFragHeapCrt, switches::kGearsInRenderer, + switches::kEnableGreasemonkey, }; for (int i = 0; i < arraysize(switch_names); ++i) { @@ -423,29 +426,66 @@ bool RenderProcessHost::Init() { // Now that the process is created, set it's backgrounding accordingly. SetBackgrounded(backgrounded_); - VisitedLinkMaster* visitedlink_master = profile_->GetVisitedLinkMaster(); - if (visitedlink_master) { - std::wstring history_table_name = visitedlink_master->GetSharedMemoryName(); - SharedMemoryHandle handle_for_process = NULL; - HANDLE target_process = process_.handle(); - if (!target_process) { - // Target process can be null if it's started with the --single-process - // flag. - target_process = GetCurrentProcess(); - } - - visitedlink_master->ShareToProcess(target_process, &handle_for_process); - DCHECK(handle_for_process); - - channel_->Send(new ViewMsg_VisitedLink_NewTable(handle_for_process)); + // Send the process its initial VisitedLink and Greasemonkey data. + HANDLE target_process = process_.handle(); + if (!target_process) { + // Target process can be null if it's started with the --single-process + // flag. + target_process = GetCurrentProcess(); } + InitVisitedLinks(target_process); + InitGreasemonkeyScripts(target_process); + if (max_page_id_ != -1) channel_->Send(new ViewMsg_SetNextPageID(max_page_id_ + 1)); return true; } +void RenderProcessHost::InitVisitedLinks(HANDLE target_process) { + VisitedLinkMaster* visitedlink_master = profile_->GetVisitedLinkMaster(); + if (!visitedlink_master) { + return; + } + + SharedMemoryHandle handle_for_process = NULL; + visitedlink_master->ShareToProcess(target_process, &handle_for_process); + DCHECK(handle_for_process); + if (handle_for_process) { + channel_->Send(new ViewMsg_VisitedLink_NewTable(handle_for_process)); + } +} + +void RenderProcessHost::InitGreasemonkeyScripts(HANDLE target_process) { + CommandLine command_line; + if (!command_line.HasSwitch(switches::kEnableGreasemonkey)) { + return; + } + + // TODO(aa): Figure out lifetime and ownership of this object + // - VisitedLinkMaster is owned by Profile, but there has been talk of + // having scripts live elsewhere besides the profile. + // - File IO should be asynchronous (see VisitedLinkMaster), but how do we + // get scripts to the first renderer without blocking startup? Should we + // cache some information across restarts? + GreasemonkeyMaster* greasemonkey_master = + Singleton<GreasemonkeyMaster>::get(); + if (!greasemonkey_master) { + return; + } + + // TODO(aa): This does blocking IO. Move to background thread. + greasemonkey_master->UpdateScripts(); + + SharedMemoryHandle handle_for_process = NULL; + greasemonkey_master->ShareToProcess(target_process, &handle_for_process); + DCHECK(handle_for_process); + if (handle_for_process) { + channel_->Send(new ViewMsg_Greasemonkey_NewScripts(handle_for_process)); + } +} + void RenderProcessHost::Attach(IPC::Channel::Listener* listener, int routing_id) { listeners_.AddWithID(listener, routing_id); diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc index 2e6d0bb..9d6da38 100644 --- a/chrome/common/chrome_paths.cc +++ b/chrome/common/chrome_paths.cc @@ -129,6 +129,11 @@ bool PathProvider(int key, std::wstring* result) { return false; file_util::AppendToPath(&cur, L"Dictionaries"); break; + case chrome::DIR_USER_SCRIPTS: + // TODO(aa): Figure out where the script directory should live. + cur = L"C:\\SCRIPTS\\"; + exists = true; // don't trigger directory creation code + break; case chrome::FILE_LOCAL_STATE: if (!PathService::Get(chrome::DIR_USER_DATA, &cur)) return false; diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h index 02b14ae..8128122 100644 --- a/chrome/common/chrome_paths.h +++ b/chrome/common/chrome_paths.h @@ -24,6 +24,7 @@ enum { DIR_LOCALES, // directory where locale resources are stored DIR_APP_DICTIONARIES, // directory where the global dictionaries are DIR_USER_DOCUMENTS, // directory for a user's "My Documents" + DIR_USER_SCRIPTS, // directory where Greasemonkey user scripts are stored FILE_RESOURCE_MODULE, // full path and filename of the module that contains // embedded resources (version, strings, images, etc.) FILE_LOCAL_STATE, // path and filename to the file in which machine/ diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 1cfc40e7..3428318 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -330,6 +330,9 @@ const wchar_t kEnableP13n[] = L"enable-p13n"; // SDCH is currently only supported server-side for searches on google.com. const wchar_t kSdchFilter[] = L"enable-sdch"; +// Enable Greasemonkey script support. +const wchar_t kEnableGreasemonkey[] = L"enable-greasemonkey"; + // Causes the browser to launch directly in incognito mode. const wchar_t kIncognito[] = L"incognito"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 4c76cdc..19b3ae6 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -128,6 +128,8 @@ extern const wchar_t kEnableP13n[]; extern const wchar_t kSdchFilter[]; +extern const wchar_t kEnableGreasemonkey[]; + extern const wchar_t kIncognito[]; extern const wchar_t kUseNewSafeBrowsing[]; diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index b7966ac..1b28898 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -155,6 +155,11 @@ IPC_BEGIN_MESSAGES(View, 1) // handle. This handle is valid in the context of the renderer IPC_MESSAGE_CONTROL1(ViewMsg_VisitedLink_NewTable, SharedMemoryHandle) + // Notification that the Greasemonkey scripts have been updated. It has one + // SharedMemoryHandle argument consisting of the pickled script data. This + // handle is valid in the context of the renderer. + IPC_MESSAGE_CONTROL1(ViewMsg_Greasemonkey_NewScripts, SharedMemoryHandle) + // Sent when the user wants to search for a word on the page (find in page). // Request parameters are passed in as a FindInPageMsg_Request struct. IPC_MESSAGE_ROUTED1(ViewMsg_Find, FindInPageRequest) 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> diff --git a/webkit/glue/webframe.h b/webkit/glue/webframe.h index 2169549..c8d73af 100644 --- a/webkit/glue/webframe.h +++ b/webkit/glue/webframe.h @@ -91,6 +91,12 @@ class WebFrame : public base::RefCounted<WebFrame> { bool replace, const GURL& fake_url) = 0; + // Executes a string of JavaScript in the web frame. The script_url param is + // the URL where the script in question can be found, if any. The renderer may + // request this URL to show the developer the source of the error. + virtual void ExecuteJavaScript(const std::string& js_code, + const std::string& script_url) = 0; + // Returns a string representing the state of the previous page load for // later use when loading as well as the uri and title of the page. The // previous page is the page that was loaded before DidCommitLoadForFrame was diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc index 4710e21..ca8997e 100644 --- a/webkit/glue/webframe_impl.cc +++ b/webkit/glue/webframe_impl.cc @@ -1595,6 +1595,13 @@ void WebFrameImpl::LoadAlternateHTMLErrorPage(const WebRequest* request, error_page_url)); } +void WebFrameImpl::ExecuteJavaScript(const std::string& js_code, + const std::string& script_url) { + frame_->loader()->executeScript(webkit_glue::StdStringToString(script_url), + 1, // base line number (for errors) + webkit_glue::StdStringToString(js_code)); +} + std::wstring WebFrameImpl::GetName() { return webkit_glue::StringToStdWString(frame_->tree()->name()); } diff --git a/webkit/glue/webframe_impl.h b/webkit/glue/webframe_impl.h index fd887d5..9a8afdb 100644 --- a/webkit/glue/webframe_impl.h +++ b/webkit/glue/webframe_impl.h @@ -94,6 +94,8 @@ class WebFrameImpl : public WebFrame { const GURL& error_page_url, bool replace, const GURL& fake_url); + virtual void ExecuteJavaScript(const std::string& js_code, + const std::string& script_url); virtual bool GetPreviousState(GURL* url, std::wstring* title, std::string* history_state) const; virtual bool GetCurrentState(GURL* url, std::wstring* title, |