diff options
-rw-r--r-- | chrome/chrome.gyp | 2 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_process_bindings.cc | 42 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_process_bindings.h | 4 | ||||
-rwxr-xr-x | chrome/renderer/extensions/renderer_extension_bindings.cc | 6 | ||||
-rwxr-xr-x | chrome/renderer/extensions/renderer_extension_bindings.h | 4 | ||||
-rw-r--r-- | chrome/renderer/js_only_v8_extensions.cc | 25 | ||||
-rw-r--r-- | chrome/renderer/js_only_v8_extensions.h | 25 | ||||
-rw-r--r-- | chrome/renderer/render_thread.cc | 20 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 4 | ||||
-rw-r--r-- | chrome/renderer/render_view_unittest.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/renderer.vcproj | 12 | ||||
-rw-r--r-- | chrome/renderer/resources/event_bindings.js | 2 | ||||
-rw-r--r-- | chrome/renderer/resources/extension_process_bindings.js | 44 | ||||
-rw-r--r-- | webkit/glue/devtools/js/base.js | 84 | ||||
-rw-r--r-- | webkit/glue/devtools/js/json.js | 14 |
15 files changed, 118 insertions, 179 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 4707153..61096fe 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1447,6 +1447,8 @@ 'renderer/external_host_bindings.h', 'renderer/external_js_object.cc', 'renderer/external_js_object.h', + 'renderer/js_only_v8_extensions.cc', + 'renderer/js_only_v8_extensions.h', 'renderer/localized_error.cc', 'renderer/localized_error.h', 'renderer/plugin_channel_host.cc', diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index 7b9533d..af8d83e 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -5,7 +5,7 @@ #include "chrome/renderer/extensions/extension_process_bindings.h" #include "chrome/common/render_messages.h" -#include "chrome/common/resource_bundle.h" +#include "chrome/renderer/extensions/bindings_utils.h" #include "chrome/renderer/render_view.h" #include "grit/renderer_resources.h" #include "third_party/WebKit/WebKit/chromium/public/WebScriptSource.h" @@ -14,14 +14,15 @@ using WebKit::WebScriptSource; using WebKit::WebString; -namespace extensions_v8 { +namespace { -const char kExtensionProcessExtensionName[] = "v8/ExtensionProcess"; +const char kExtensionName[] = "chrome/ExtensionProcessBindings"; -class ExtensionProcessBindingsWrapper : public v8::Extension { +class ExtensionImpl : public v8::Extension { public: - ExtensionProcessBindingsWrapper() - : v8::Extension(kExtensionProcessExtensionName, GetSource()) {} + ExtensionImpl() : v8::Extension( + kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(), + NULL, NULL) {} static void SetFunctionNames(const std::vector<std::string>& names) { function_names_ = new std::set<std::string>(); @@ -42,21 +43,6 @@ class ExtensionProcessBindingsWrapper : public v8::Extension { } private: - static const char* GetSource() { - // This is weird. The v8::Extension constructor expects a null-terminated - // string which it doesn't own (all current uses are constant). The value - // returned by GetDataResource is *not* null-terminated, and simply - // converting it to a string, then using that string's c_str() in this - // class's constructor doesn't work because the resulting string is stack- - // allocated. - if (!source_) - source_ = new std::string( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_EXTENSION_PROCESS_BINDINGS_JS).as_string()); - - return source_->c_str(); - } - static v8::Handle<v8::Value> GetNextCallbackId(const v8::Arguments& args) { static int next_callback_id = 0; return v8::Integer::New(next_callback_id++); @@ -87,26 +73,22 @@ class ExtensionProcessBindingsWrapper : public v8::Extension { return v8::Undefined(); } - static std::string* source_; static std::set<std::string>* function_names_; }; -std::string* ExtensionProcessBindingsWrapper::source_; -std::set<std::string>* ExtensionProcessBindingsWrapper::function_names_; +std::set<std::string>* ExtensionImpl::function_names_; +} // namespace -// static v8::Extension* ExtensionProcessBindings::Get() { - return new ExtensionProcessBindingsWrapper(); + return new ExtensionImpl(); } -// static void ExtensionProcessBindings::SetFunctionNames( const std::vector<std::string>& names) { - ExtensionProcessBindingsWrapper::SetFunctionNames(names); + ExtensionImpl::SetFunctionNames(names); } -// static void ExtensionProcessBindings::ExecuteCallbackInFrame( WebFrame* frame, int callback_id, const std::string& response) { std::string code = "chromium._dispatchCallback("; @@ -121,5 +103,3 @@ void ExtensionProcessBindings::ExecuteCallbackInFrame( frame->ExecuteScript(WebScriptSource(WebString::fromUTF8(code))); } - -} // namespace extensions_v8 diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h index 53fe17d..8246b4b 100644 --- a/chrome/renderer/extensions/extension_process_bindings.h +++ b/chrome/renderer/extensions/extension_process_bindings.h @@ -14,8 +14,6 @@ class WebFrame;
-namespace extensions_v8 {
-
class ExtensionProcessBindings {
public:
static void SetFunctionNames(const std::vector<std::string>& names);
@@ -24,6 +22,4 @@ class ExtensionProcessBindings { const std::string& response);
};
-} // namespace extensions_v8
-
#endif // CHROME_RENDERER_EXTENSIONS_EXTENSION_PROCESS_BINDINGS_H_
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc index 572b00c..d9a73e6 100755 --- a/chrome/renderer/extensions/renderer_extension_bindings.cc +++ b/chrome/renderer/extensions/renderer_extension_bindings.cc @@ -27,7 +27,7 @@ namespace { // We use the generic interface so that unit tests can inject a mock. RenderThreadBase* render_thread_ = NULL; -const char* kExtensionName = "v8/RendererExtensionBindings"; +const char* kExtensionName = "chrome/RendererExtensionBindings"; const char* kExtensionDeps[] = { EventBindings::kName }; class ExtensionImpl : public v8::Extension { @@ -76,8 +76,6 @@ class ExtensionImpl : public v8::Extension { } // namespace -namespace extensions_v8 { - v8::Extension* RendererExtensionBindings::Get(RenderThreadBase* render_thread) { render_thread_ = render_thread; return new ExtensionImpl(); @@ -100,5 +98,3 @@ void RendererExtensionBindings::HandleMessage(const std::string& message, EventBindings::CallFunction("chromium.Port.dispatchOnMessage_", arraysize(argv), argv); } - -} // namespace extensions_v8 diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h index b0d04de..5ff474e 100755 --- a/chrome/renderer/extensions/renderer_extension_bindings.h +++ b/chrome/renderer/extensions/renderer_extension_bindings.h @@ -11,8 +11,6 @@ class RenderThreadBase; -namespace extensions_v8 { - // This class adds extension-related javascript bindings to a renderer. It is // used by both web renderers and extension processes. class RendererExtensionBindings { @@ -27,6 +25,4 @@ class RendererExtensionBindings { static void HandleMessage(const std::string& message, int port_id); }; -} // namespace extensions_v8 - #endif // CHROME_RENDERER_EXTENSIONS_RENDERER_EXTENSION_BINDINGS_H_ diff --git a/chrome/renderer/js_only_v8_extensions.cc b/chrome/renderer/js_only_v8_extensions.cc new file mode 100644 index 0000000..5ca3ae7 --- /dev/null +++ b/chrome/renderer/js_only_v8_extensions.cc @@ -0,0 +1,25 @@ +// Copyright (c) 2009 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/js_only_v8_extensions.h" + +#include "chrome/renderer/extensions/bindings_utils.h" +#include "grit/webkit_resources.h" + +// BaseJsV8Extension +const char* BaseJsV8Extension::kName = "chrome/base"; +v8::Extension* BaseJsV8Extension::Get() { + return new v8::Extension(kName, GetStringResource<IDR_DEVTOOLS_BASE_JS>(), + 0, NULL); +} + +// JsonJsV8Extension +const char* JsonJsV8Extension::kName = "chrome/json"; +v8::Extension* JsonJsV8Extension::Get() { + static const char* deps[] = { + BaseJsV8Extension::kName + }; + return new v8::Extension(kName, GetStringResource<IDR_DEVTOOLS_JSON_JS>(), + arraysize(deps), deps); +} diff --git a/chrome/renderer/js_only_v8_extensions.h b/chrome/renderer/js_only_v8_extensions.h new file mode 100644 index 0000000..d7fc7a8 --- /dev/null +++ b/chrome/renderer/js_only_v8_extensions.h @@ -0,0 +1,25 @@ +// Copyright (c) 2009 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_JS_ONLY_V8_EXTENSIONS_H_ +#define CHROME_RENDERER_JS_ONLY_V8_EXTENSIONS_H_ + +#include "v8/include/v8.h" + +// This file contains various V8 Extensions that are JavaScript only, and +// don't have any C++ native functions. + +class BaseJsV8Extension { + public: + static const char* kName; + static v8::Extension* Get(); +}; + +class JsonJsV8Extension { + public: + static const char* kName; + static v8::Extension* Get(); +}; + +#endif // CHROME_RENDERER_JS_ONLY_V8_EXTENSIONS_H_ diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index ea0cf94..2865cc4 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -28,6 +28,7 @@ #include "chrome/renderer/extensions/event_bindings.h" #include "chrome/renderer/extensions/extension_process_bindings.h" #include "chrome/renderer/extensions/renderer_extension_bindings.h" +#include "chrome/renderer/js_only_v8_extensions.h" #include "chrome/renderer/loadtimes_extension_bindings.h" #include "chrome/renderer/net/render_dns_master.h" #include "chrome/renderer/render_process.h" @@ -162,7 +163,7 @@ void RenderThread::OnUpdateUserScripts( void RenderThread::OnSetExtensionFunctionNames( const std::vector<std::string>& names) { - extensions_v8::ExtensionProcessBindings::SetFunctionNames(names); + ExtensionProcessBindings::SetFunctionNames(names); } void RenderThread::OnControlMessageReceived(const IPC::Message& msg) { @@ -288,13 +289,18 @@ void RenderThread::EnsureWebKitInitialized() { WebKit::registerExtension(extensions_v8::IntervalExtension::Get()); WebKit::registerExtension(extensions_v8::LoadTimesExtension::Get()); + WebKit::registerExtension(ExtensionProcessBindings::Get(), + WebKit::WebString::fromUTF8(chrome::kExtensionScheme)); + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + // TODO(aa): Add a way to restrict extensions to the content script context + // only so that we don't have to gate these on --enable-extensions. if (command_line.HasSwitch(switches::kEnableExtensions)) { + WebKit::registerExtension(BaseJsV8Extension::Get()); + WebKit::registerExtension(JsonJsV8Extension::Get()); WebKit::registerExtension(EventBindings::Get()); - WebKit::registerExtension( - extensions_v8::RendererExtensionBindings::Get(this)); - WebKit::registerExtension(extensions_v8::ExtensionProcessBindings::Get(), - WebKit::WebString::fromUTF8(chrome::kExtensionScheme)); + WebKit::registerExtension(RendererExtensionBindings::Get(this)); } if (command_line.HasSwitch(switches::kPlaybackMode) || @@ -308,10 +314,10 @@ void RenderThread::EnsureWebKitInitialized() { } void RenderThread::OnExtensionHandleConnect(int port_id) { - extensions_v8::RendererExtensionBindings::HandleConnect(port_id); + RendererExtensionBindings::HandleConnect(port_id); } void RenderThread::OnExtensionHandleMessage(const std::string& message, int port_id) { - extensions_v8::RendererExtensionBindings::HandleMessage(message, port_id); + RendererExtensionBindings::HandleMessage(message, port_id); } diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 6605f4e..b4fc6d5 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -3031,8 +3031,8 @@ void RenderView::OnExtensionResponse(int callback_id, if (!web_frame) return; // The frame went away. - extensions_v8::ExtensionProcessBindings::ExecuteCallbackInFrame( - web_frame, callback_id, response); + ExtensionProcessBindings::ExecuteCallbackInFrame(web_frame, callback_id, + response); pending_extension_callbacks_.Remove(callback_id); } diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc index 95a584bb..a70480c 100644 --- a/chrome/renderer/render_view_unittest.cc +++ b/chrome/renderer/render_view_unittest.cc @@ -68,8 +68,7 @@ class RenderViewTest : public testing::Test { virtual void SetUp() { WebKit::initialize(&webkitclient_); WebKit::registerExtension(EventBindings::Get()); - WebKit::registerExtension( - extensions_v8::RendererExtensionBindings::Get(&render_thread_)); + WebKit::registerExtension(RendererExtensionBindings::Get(&render_thread_)); mock_process_.reset(new MockProcess()); @@ -404,7 +403,7 @@ TEST_F(RenderViewTest, ExtensionMessagesOpenChannel) { // Now simulate getting a message back from the other side. render_thread_.sink().ClearMessages(); const int kPortId = 0; - extensions_v8::RendererExtensionBindings::HandleMessage("42", kPortId); + RendererExtensionBindings::HandleMessage("42", kPortId); // Verify that we got it. const IPC::Message* alert_msg = @@ -434,7 +433,7 @@ TEST_F(RenderViewTest, ExtensionMessagesOnConnect) { // Simulate a new connection being opened. const int kPortId = 0; - extensions_v8::RendererExtensionBindings::HandleConnect(kPortId); + RendererExtensionBindings::HandleConnect(kPortId); // Verify that we handled the new connection by posting a message. const IPC::Message* post_msg = @@ -447,7 +446,7 @@ TEST_F(RenderViewTest, ExtensionMessagesOnConnect) { // Now simulate getting a message back from the channel opener. render_thread_.sink().ClearMessages(); - extensions_v8::RendererExtensionBindings::HandleMessage("42", kPortId); + RendererExtensionBindings::HandleMessage("42", kPortId); // Verify that we got it. const IPC::Message* alert_msg = diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj index fca563e..56f9e82 100644 --- a/chrome/renderer/renderer.vcproj +++ b/chrome/renderer/renderer.vcproj @@ -201,6 +201,10 @@ > </File> <File + RelativePath=".\extensions\extension_process_bindings.h" + > + </File> + <File RelativePath=".\extensions\renderer_extension_bindings.cc" > </File> @@ -274,6 +278,14 @@ > </File> <File + RelativePath=".\js_only_v8_extensions.cc" + > + </File> + <File + RelativePath=".\js_only_v8_extensions.h" + > + </File> + <File RelativePath=".\loadtimes_extension_bindings.cc" > </File> diff --git a/chrome/renderer/resources/event_bindings.js b/chrome/renderer/resources/event_bindings.js index de5b3a9..42f1175 100644 --- a/chrome/renderer/resources/event_bindings.js +++ b/chrome/renderer/resources/event_bindings.js @@ -25,7 +25,7 @@ var chromium = chromium || {}; chromium.Event.dispatchJSON_ = function(name, data) { if (chromium.Event.attached_[name]) { if (data) { - data = chromium.json.deserialize_(data); + data = chromium.json.parse(data); } chromium.Event.attached_[name].dispatch_(data); } diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js index 221f3fd..85d4d53 100644 --- a/chrome/renderer/resources/extension_process_bindings.js +++ b/chrome/renderer/resources/extension_process_bindings.js @@ -6,53 +6,13 @@ var chromium; // callback handling var callbacks = []; chromium._dispatchCallback = function(callbackId, str) { - // We shouldn't be receiving evil JSON unless the browser is owned, but just - // to be safe, we sanitize it. This regex mania was borrowed from json2, - // from json.org. - if (!/^[\],:{}\s]*$/.test( - str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). - replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). - replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) - throw new Error("Unexpected characters in incoming JSON response."); - - // This is lame. V8 disallows direct access to eval() in extensions (see: - // v8::internal::Parser::ParseLeftHandSideExpression()). So we must use - // this supa-jank hack instead. We really need native JSON. - str = 'return ' + str; - callbacks[callbackId](new Function(str)()); + callbacks[callbackId](goog.json.parse(str)); delete callbacks[callbackId]; }; - // Quick and dirty json serialization. - // TODO(aa): Did I mention we need native JSON? - function serialize(thing) { - switch (typeof thing) { - case 'string': - return '\"' + thing.replace('\\', '\\\\').replace('\"', '\\\"') + '\"'; - case 'boolean': - case 'number': - return String(thing); - case 'object': - if (thing === null) - return String(thing) - var items = []; - if (thing.constructor == Array) { - for (var i = 0; i < thing.length; i++) - items.push(serialize(thing[i])); - return '[' + items.join(',') + ']'; - } else { - for (var p in thing) - items.push(serialize(p) + ':' + serialize(thing[p])); - return '{' + items.join(',') + '}'; - } - default: - return ''; - } - } - // Send an API request and optionally register a callback. function sendRequest(request, args, callback) { - var sargs = serialize(args); + var sargs = goog.json.serialize(args); var callbackId = -1; if (callback) { native function GetNextCallbackId(); diff --git a/webkit/glue/devtools/js/base.js b/webkit/glue/devtools/js/base.js index 307765c..8f029a1 100644 --- a/webkit/glue/devtools/js/base.js +++ b/webkit/glue/devtools/js/base.js @@ -25,6 +25,14 @@ // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. +// NOTE: This file has been changed from the one on doctype. The following +// changes were made: +// - Removed goog.globalEval because it calls eval() which is not allowed from +// inside v8 extensions. If we ever need to use globalEval, we will need to +// find a way to work around this problem. +// - Remove Function.prototype.apply() emulation for the same reason. This one +// is useless anyway because V8 supports apply() natively. + /** * @fileoverview Bootstrap for the Google JS Library */ @@ -811,47 +819,6 @@ goog.now = Date.now || (function() { /** - * Evals javascript in the global scope. In IE this uses execScript, other - * browsers use goog.global.eval. If goog.global.eval does not evaluate in the - * global scope (for example, in Safari), appends a script tag instead. - * Throws an exception if neither execScript or eval is defined. - * @param {string} script JavaScript string. - */ -goog.globalEval = function(script) { - if (goog.global.execScript) { - goog.global.execScript(script, 'JavaScript'); - } else if (goog.global.eval) { - // Test to see if eval works - if (goog.evalWorksForGlobals_ == null) { - goog.global.eval('var _et_ = 1;'); - if (typeof goog.global['_et_'] != 'undefined') { - delete goog.global['_et_']; - goog.evalWorksForGlobals_ = true; - } else { - goog.evalWorksForGlobals_ = false; - } - } - - if (goog.evalWorksForGlobals_) { - goog.global.eval(script); - } else { - var doc = goog.global.document; - var scriptElt = doc.createElement('script'); - scriptElt.type = 'text/javascript'; - scriptElt.defer = false; - // Note(pupius): can't use .innerHTML since "t('<test>')" will fail and - // .text doesn't work in Safari 2. Therefore we append a text node. - scriptElt.appendChild(doc.createTextNode(script)); - doc.body.appendChild(scriptElt); - doc.body.removeChild(scriptElt); - } - } else { - throw Error('goog.globalEval not available'); - } -}; - - -/** * Abstract implementation of goog.getMsg for use with localized messages * @param {string} str Translatable string, places holders in the form.{$foo} * @param {Object} opt_values Map of place holder name to value. @@ -912,41 +879,6 @@ goog.exportProperty = function(object, publicName, symbol) { /** - * Some old browsers don't have Function.apply. So sad. We emulate it for them. - * @param {Object} oScope The Object within the scope of which the Function is - * applied. In other words, |this| will be bound to oScope within the body - * of the Function called with apply. - * @param {Array} args Arguments for the function. - * @return {Object} Value returned from the function. - */ -if (!Function.prototype.apply) { - Function.prototype.apply = function(oScope, args) { - var sarg = []; - var rtrn, call; - - if (!oScope) oScope = goog.global; - if (!args) args = []; - - for (var i = 0; i < args.length; i++) { - sarg[i] = 'args[' + i + ']'; - } - - call = 'oScope.__applyTemp__.peek().(' + sarg.join(',') + ');'; - - if (!oScope['__applyTemp__']) { - oScope['__applyTemp__'] = []; - } - - oScope['__applyTemp__'].push(this); - rtrn = eval(call); - oScope['__applyTemp__'].pop(); - - return rtrn; - }; -} - - -/** * An alias to the {@link goog.bind()} global function. * * Usage: diff --git a/webkit/glue/devtools/js/json.js b/webkit/glue/devtools/js/json.js index 227d7d1..252e4ac 100644 --- a/webkit/glue/devtools/js/json.js +++ b/webkit/glue/devtools/js/json.js @@ -25,6 +25,13 @@ // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. +// NOTE: This file has been changed from the one on doctype. The following +// changes were made: +// - Modified unsafeParse() to use new Function() instead of eval() because eval +// is not allowed inside v8 extensions. +// - Modified parse() to delegate to unsafeParse() instead of calling eval() +// directly. + /** * @fileoverview JSON utility functions */ @@ -103,7 +110,7 @@ goog.json.parse = function(s) { if (goog.json.isValid_(s)) { /** @preserveTry */ try { - return eval('(' + s + ')'); + return goog.json.unsafeParse(s); } catch (ex) { } } @@ -119,7 +126,10 @@ goog.json.parse = function(s) { * @return {Object} The object generated from the JSON string. */ goog.json.unsafeParse = function(s) { - return eval('(' + s + ')'); + // This is lame. V8 disallows direct access to eval() in extensions (see: + // v8::internal::Parser::ParseLeftHandSideExpression()). So we must use this + // nasty hack instead. + return new Function('return ('+ s + ')')(); }; |