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/browser | |
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/browser')
-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 |
4 files changed, 183 insertions, 15 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); |