diff options
author | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-22 02:35:54 +0000 |
---|---|---|
committer | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-22 02:35:54 +0000 |
commit | 31bbfd7310d8578a694564307310acf4a7161572 (patch) | |
tree | 93dbc9d9076d6e5ffdbeaa779afb4b6ce75fe3b9 | |
parent | b518fa10e24b183a15b8c194ddc09527c0d07768 (diff) | |
download | chromium_src-31bbfd7310d8578a694564307310acf4a7161572.zip chromium_src-31bbfd7310d8578a694564307310acf4a7161572.tar.gz chromium_src-31bbfd7310d8578a694564307310acf4a7161572.tar.bz2 |
Make the externally connectable browser test clobber all of the builtins,
except for a very small subset of them, and use the safe builtins to make the
test pass.
This will give us a decent sense of confidence that web pages can't
accidentally override builtins in a way that breaks us, though there are still
infinite ways for an extension to deliberately break itself.
BUG=55316
R=jyasskin@chromium.org
Review URL: https://codereview.chromium.org/17451011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207995 0039d316-1c4b-4281-b951-d872f2087c98
41 files changed, 217 insertions, 126 deletions
diff --git a/chrome/renderer/extensions/module_system.cc b/chrome/renderer/extensions/module_system.cc index 29575b2..822c15e 100644 --- a/chrome/renderer/extensions/module_system.cc +++ b/chrome/renderer/extensions/module_system.cc @@ -189,6 +189,8 @@ v8::Handle<v8::Value> ModuleSystem::RequireForJsInner( exports = v8::Object::New(); v8::Handle<v8::Object> natives(NewInstance()); + CHECK(!natives.IsEmpty()); // this can happen if v8 has issues + // These must match the argument order in WrapSource. v8::Handle<v8::Value> args[] = { // CommonJS. @@ -200,6 +202,8 @@ v8::Handle<v8::Value> ModuleSystem::RequireForJsInner( context_->safe_builtins()->GetFunction(), context_->safe_builtins()->GetJSON(), context_->safe_builtins()->GetObjekt(), + context_->safe_builtins()->GetRegExp(), + context_->safe_builtins()->GetString(), }; { v8::TryCatch try_catch; @@ -483,7 +487,7 @@ v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { // Keep in order with the arguments in RequireForJsInner. v8::Handle<v8::String> left = v8::String::New( "(function(require, requireNative, exports," - "$Array, $Function, $JSON, $Object) {" + "$Array, $Function, $JSON, $Object, $RegExp, $String) {" "'use strict';"); v8::Handle<v8::String> right = v8::String::New("\n})"); return handle_scope.Close( diff --git a/chrome/renderer/extensions/safe_builtins.cc b/chrome/renderer/extensions/safe_builtins.cc index 05f67fc..2a58bf2 100644 --- a/chrome/renderer/extensions/safe_builtins.cc +++ b/chrome/renderer/extensions/safe_builtins.cc @@ -150,17 +150,21 @@ class ExtensionImpl : public v8::Extension { static void Apply(const v8::FunctionCallbackInfo<v8::Value>& info) { CHECK(info.Length() == 5 && info[0]->IsFunction() && // function - // info[1]->Object() // recv (will throw error not check) + // info[1] could be an object or a string info[2]->IsObject() && // args info[3]->IsInt32() && // first_arg_index info[4]->IsInt32()); // args_length - if (!info[1]->IsObject()) { + v8::Local<v8::Function> function = info[0].As<v8::Function>(); + v8::Local<v8::Object> recv; + if (info[1]->IsObject()) { + recv = info[1]->ToObject(); + } else if (info[1]->IsString()) { + recv = v8::StringObject::New(info[1]->ToString())->ToObject(); + } else { v8::ThrowException(v8::Exception::TypeError(v8::String::New( "The first argument is the receiver and must be an object"))); return; } - v8::Local<v8::Function> function = info[0].As<v8::Function>(); - v8::Local<v8::Object> recv = info[1]->ToObject(); v8::Local<v8::Object> args = info[2]->ToObject(); int first_arg_index = static_cast<int>(info[3]->ToInt32()->Value()); int args_length = static_cast<int>(info[4]->ToInt32()->Value()); @@ -214,4 +218,12 @@ v8::Local<v8::Object> SafeBuiltins::GetObjekt() const { return Load("Object", context_->v8_context()); } +v8::Local<v8::Object> SafeBuiltins::GetRegExp() const { + return Load("RegExp", context_->v8_context()); +} + +v8::Local<v8::Object> SafeBuiltins::GetString() const { + return Load("String", context_->v8_context()); +} + } // namespace extensions diff --git a/chrome/renderer/extensions/safe_builtins.h b/chrome/renderer/extensions/safe_builtins.h index 3be54c1..f34a949 100644 --- a/chrome/renderer/extensions/safe_builtins.h +++ b/chrome/renderer/extensions/safe_builtins.h @@ -34,6 +34,8 @@ class SafeBuiltins { // NOTE(kalman): VS2010 won't compile "GetObject", it mysteriously renames it // to "GetObjectW" - hence GetObjekt. Sorry. v8::Local<v8::Object> GetObjekt() const; + v8::Local<v8::Object> GetRegExp() const; + v8::Local<v8::Object> GetString() const; private: ChromeV8Context* context_; diff --git a/chrome/renderer/resources/extensions/ad_view.js b/chrome/renderer/resources/extensions/ad_view.js index 8c3b27b..3d0a76c 100644 --- a/chrome/renderer/resources/extensions/ad_view.js +++ b/chrome/renderer/resources/extensions/ad_view.js @@ -160,7 +160,7 @@ AdView.prototype.setupAdviewNodeMethods_ = function() { var self = this; $Array.forEach(AD_VIEW_API_METHODS, function(apiMethod) { self.adviewNode_[apiMethod] = function(var_args) { - return self.browserPluginNode_[apiMethod].apply( + return $Function.apply(self.browserPluginNode_[apiMethod], self.browserPluginNode_, arguments); }; }, this); diff --git a/chrome/renderer/resources/extensions/app_custom_bindings.js b/chrome/renderer/resources/extensions/app_custom_bindings.js index 2bc8690..733395d 100644 --- a/chrome/renderer/resources/extensions/app_custom_bindings.js +++ b/chrome/renderer/resources/extensions/app_custom_bindings.js @@ -22,8 +22,8 @@ function wrapForLogging(fun) { // TODO(ataly): We need to make sure we use the right prototype for // fun.apply. Array slice can either be rewritten or similarly defined. logActivity.LogAPICall(id, "app." + fun.name, - Array.prototype.slice.call(arguments)); - return fun.apply(this, arguments); + $Array.slice(arguments)); + return $Function.apply(fun, this, arguments); }); } diff --git a/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js b/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js index 431633f..0411d32 100644 --- a/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js +++ b/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js @@ -27,7 +27,7 @@ eventBindings.registerArgumentMassager('app.runtime.onLaunched', if (err) { console.error('Error getting fileEntry, code: ' + err.code); } else { - items.push(item); + $Array.push(items, item); } if (--numItems === 0) { if (items.length === 0) { diff --git a/chrome/renderer/resources/extensions/binding.js b/chrome/renderer/resources/extensions/binding.js index 55f6eda..a53737c 100644 --- a/chrome/renderer/resources/extensions/binding.js +++ b/chrome/renderer/resources/extensions/binding.js @@ -40,9 +40,9 @@ APIFunctions.prototype.registerUnavailable = function(apiName) { APIFunctions.prototype.setHook_ = function(apiName, propertyName, customizedFunction) { - if (this.unavailableApiFunctions_.hasOwnProperty(apiName)) + if ($Object.hasOwnProperty(this.unavailableApiFunctions_, apiName)) return; - if (!this.apiFunctions_.hasOwnProperty(apiName)) + if (!$Object.hasOwnProperty(this.apiFunctions_, apiName)) throw new Error('Tried to set hook for unknown API "' + apiName + '"'); this.apiFunctions_[apiName][propertyName] = customizedFunction; }; @@ -50,15 +50,14 @@ APIFunctions.prototype.setHook_ = APIFunctions.prototype.setHandleRequest = function(apiName, customizedFunction) { var prefix = this.namespace; - // TODO(ataly): Need to replace/redefine apply and slice. return this.setHook_(apiName, 'handleRequest', function() { - var ret = customizedFunction.apply(this, arguments); + var ret = $Function.apply(customizedFunction, this, arguments); // Logs API calls to the Activity Log if it doesn't go through an // ExtensionFunction. if (!sendRequestHandler.getCalledSendRequest()) logActivity.LogAPICall(extensionId, prefix + "." + apiName, - Array.prototype.slice.call(arguments)); + $Array.slice(arguments)); return ret; }); }; @@ -107,7 +106,7 @@ function getPlatform() { ]; for (var i = 0; i < platforms.length; i++) { - if (platforms[i][0].test(navigator.appVersion)) { + if ($RegExp.test(platforms[i][0], navigator.appVersion)) { return platforms[i][1]; } } @@ -176,7 +175,7 @@ Binding.prototype = { // interact with, and second the current extension ID. See where // |customHooks| is used. registerCustomHook: function(fn) { - this.customHooks_.push(fn); + $Array.push(this.customHooks_, fn); }, // TODO(kalman/cduvall): Refactor this so |runHooks_| is not needed. @@ -207,7 +206,7 @@ Binding.prototype = { return shouldCheck; $Array.forEach(['functions', 'events'], function(type) { - if (schema.hasOwnProperty(type)) { + if ($Object.hasOwnProperty(schema, type)) { $Array.forEach(schema[type], function(node) { if ('unprivileged' in node) shouldCheck = true; @@ -218,7 +217,7 @@ Binding.prototype = { return shouldCheck; for (var property in schema.properties) { - if (schema.hasOwnProperty(property) && + if ($Object.hasOwnProperty(schema, property) && 'unprivileged' in schema.properties[property]) { shouldCheck = true; break; @@ -238,7 +237,7 @@ Binding.prototype = { var mod = {}; - var namespaces = schema.namespace.split('.'); + var namespaces = $String.split(schema.namespace, '.'); for (var index = 0, name; name = namespaces[index]; index++) { mod[name] = mod[name] || {}; mod = mod[name]; @@ -301,19 +300,22 @@ Binding.prototype = { this.apiFunctions_.register(functionDef.name, apiFunction); mod[functionDef.name] = $Function.bind(function() { - var args = Array.prototype.slice.call(arguments); + var args = $Array.slice(arguments); if (this.updateArgumentsPreValidate) - args = this.updateArgumentsPreValidate.apply(this, args); + args = $Function.apply(this.updateArgumentsPreValidate, this, args); args = schemaUtils.normalizeArgumentsAndValidate(args, this); - if (this.updateArgumentsPostValidate) - args = this.updateArgumentsPostValidate.apply(this, args); + if (this.updateArgumentsPostValidate) { + args = $Function.apply(this.updateArgumentsPostValidate, + this, + args); + } sendRequestHandler.clearCalledSendRequest(); var retval; if (this.handleRequest) { - retval = this.handleRequest.apply(this, args); + retval = $Function.apply(this.handleRequest, this, args); } else { var optArgs = { customCallback: this.customCallback @@ -403,7 +405,7 @@ Binding.prototype = { // not as an array), so we have to fake calling |new| on the // constructor. value = { __proto__: constructor.prototype }; - constructor.apply(value, args); + $Function.apply(constructor, value, args); // Recursively add properties. addProperties(value, propertyDef); } else if (type === 'object') { @@ -421,7 +423,7 @@ Binding.prototype = { addProperties(mod, schema); var availability = GetAvailability(schema.namespace); - if (!availability.is_available && Object.keys(mod).length == 0) { + if (!availability.is_available && $Object.keys(mod).length == 0) { console.error('chrome.' + schema.namespace + ' is not available: ' + availability.message); return; diff --git a/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js b/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js index 07697d4..a125877 100644 --- a/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js +++ b/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js @@ -121,7 +121,7 @@ binding.registerCustomHook(function(api) { apiFunctions.setUpdateArgumentsPostValidate('getDevices', function() { - var args = Array.prototype.slice.call(arguments); + var args = $Array.slice(arguments); if (bluetooth.getDevicesState != null) { throw new Error('Concurrent calls to getDevices are not allowed.'); @@ -131,7 +131,7 @@ binding.registerCustomHook(function(api) { if (typeof(args[args.length - 1]) == 'function') { state.finalCallback = args.pop(); - args.push( + $Array.push(args, function() { if (chrome.runtime.lastError) { finishDeviceSearch(); diff --git a/chrome/renderer/resources/extensions/chrome_setting.js b/chrome/renderer/resources/extensions/chrome_setting.js index b2194b1..8d6f29e 100644 --- a/chrome/renderer/resources/extensions/chrome_setting.js +++ b/chrome/renderer/resources/extensions/chrome_setting.js @@ -7,7 +7,7 @@ var sendRequest = require('sendRequest').sendRequest; var validate = require('schemaUtils').validate; function extendSchema(schema) { - var extendedSchema = schema.slice(); + var extendedSchema = $Array.slice(schema); extendedSchema.unshift({'type': 'string'}); return extendedSchema; } @@ -21,7 +21,8 @@ function ChromeSetting(prefKey, valueSchema) { extendSchema(getSchema)); }; this.set = function(details, callback) { - var setSchema = this.functionSchemas.set.definition.parameters.slice(); + var setSchema = $Array.slice( + this.functionSchemas.set.definition.parameters); setSchema[0].properties.value = valueSchema; validate([details, callback], setSchema); return sendRequest('types.ChromeSetting.set', diff --git a/chrome/renderer/resources/extensions/content_setting.js b/chrome/renderer/resources/extensions/content_setting.js index 990d269..c76b74b 100644 --- a/chrome/renderer/resources/extensions/content_setting.js +++ b/chrome/renderer/resources/extensions/content_setting.js @@ -8,7 +8,7 @@ var sendRequest = require('sendRequest').sendRequest; var validate = require('schemaUtils').validate; function extendSchema(schema) { - var extendedSchema = schema.slice(); + var extendedSchema = $Array.slice(schema); extendedSchema.unshift({'type': 'string'}); return extendedSchema; } @@ -22,7 +22,8 @@ function ContentSetting(contentType, settingSchema) { extendSchema(getSchema)); }; this.set = function(details, callback) { - var setSchema = this.functionSchemas.set.definition.parameters.slice(); + var setSchema = $Array.slice( + this.functionSchemas.set.definition.parameters); setSchema[0].properties.setting = settingSchema; validate([details, callback], setSchema); return sendRequest('contentSettings.set', diff --git a/chrome/renderer/resources/extensions/content_watcher.js b/chrome/renderer/resources/extensions/content_watcher.js index c060276..6005a78 100644 --- a/chrome/renderer/resources/extensions/content_watcher.js +++ b/chrome/renderer/resources/extensions/content_watcher.js @@ -10,7 +10,7 @@ exports.FindMatchingSelectors = function(cssSelectors) { $Array.forEach(cssSelectors, function(selector, index) { try { if (document.querySelector(selector) != null) - result.push(index); + $Array.push(result, index); } catch (exception) { throw new Error("query Selector failed on '" + selector + "': " + exception.stack); diff --git a/chrome/renderer/resources/extensions/context_menus_custom_bindings.js b/chrome/renderer/resources/extensions/context_menus_custom_bindings.js index f143ee6..5323f73 100644 --- a/chrome/renderer/resources/extensions/context_menus_custom_bindings.js +++ b/chrome/renderer/resources/extensions/context_menus_custom_bindings.js @@ -39,7 +39,7 @@ binding.registerCustomHook(function(bindingsAPI) { var id = arguments[0].menuItemId; var onclick = contextMenus.handlersForId(id)[id]; if (onclick) { - onclick.apply(null, arguments); + $Function.apply(onclick, null, arguments); } }); }; diff --git a/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js b/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js index 066413e..beb5409 100644 --- a/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js +++ b/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js @@ -26,7 +26,7 @@ binding.registerCustomHook( function(api) { // generated union dictionary against the schema for |typeId|. function setupInstance(instance, parameters, typeId) { for (var key in parameters) { - if (parameters.hasOwnProperty(key)) { + if ($Object.hasOwnProperty(parameters, key)) { instance[key] = parameters[key]; } } diff --git a/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js b/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js index 2034cc8..641b782 100644 --- a/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js +++ b/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js @@ -26,7 +26,7 @@ binding.registerCustomHook(function(api) { // generated union dictionary against the schema for |typeId|. function setupInstance(instance, parameters, typeId) { for (var key in parameters) { - if (parameters.hasOwnProperty(key)) { + if ($Object.hasOwnProperty(parameters, key)) { instance[key] = parameters[key]; } } diff --git a/chrome/renderer/resources/extensions/entry_id_manager.js b/chrome/renderer/resources/extensions/entry_id_manager.js index 8933239..669e7bf 100644 --- a/chrome/renderer/resources/extensions/entry_id_manager.js +++ b/chrome/renderer/resources/extensions/entry_id_manager.js @@ -17,7 +17,7 @@ function computeId(entry) { if (!fileSystemId) return null; // Strip the leading '/' from the path. - return fileSystemId + ':' + entry.fullPath.slice(1); + return fileSystemId + ':' + $String.slice(entry.fullPath, 1); } function registerEntry(id, entry) { diff --git a/chrome/renderer/resources/extensions/event.js b/chrome/renderer/resources/extensions/event.js index 8c352d3..9e7f0b1 100644 --- a/chrome/renderer/resources/extensions/event.js +++ b/chrome/renderer/resources/extensions/event.js @@ -109,14 +109,14 @@ FilteredAttachmentStrategy.prototype.getListenersByIDs = function(ids) { var result = []; for (var i = 0; i < ids.length; i++) - result.push(this.listenerMap_[ids[i]]); + $Array.push(result, this.listenerMap_[ids[i]]); return result; }; function parseEventOptions(opt_eventOptions) { function merge(dest, src) { for (var k in src) { - if (!dest.hasOwnProperty(k)) { + if (!$Object.hasOwnProperty(dest, k)) { dest[k] = src[k]; } } @@ -224,7 +224,7 @@ } var listener = {callback: cb, filters: filters}; this.attach_(listener); - this.listeners_.push(listener); + $Array.push(this.listeners_, listener); }; Event.prototype.attach_ = function(listener) { @@ -249,7 +249,7 @@ if (idx == -1) return; - var removedListener = this.listeners_.splice(idx, 1)[0]; + var removedListener = $Array.splice(this.listeners_, idx, 1)[0]; this.attachmentStrategy_.onRemovedListener(removedListener); if (this.listeners_.length == 0) { @@ -308,15 +308,15 @@ // Make a copy of the listeners in case the listener list is modified // while dispatching the event. - var listeners = - this.attachmentStrategy_.getListenersByIDs(listenerIDs).slice(); + var listeners = $Array.slice( + this.attachmentStrategy_.getListenersByIDs(listenerIDs)); var results = []; for (var i = 0; i < listeners.length; i++) { try { var result = this.dispatchToListener(listeners[i].callback, args); if (result !== undefined) - results.push(result); + $Array.push(results, result); } catch (e) { var errorMessage = "Error in event handler"; if (this.eventName_) @@ -331,13 +331,13 @@ // Can be overridden to support custom dispatching. Event.prototype.dispatchToListener = function(callback, args) { - return callback.apply(null, args); + return $Function.apply(callback, null, args); } // Dispatches this event object to all listeners, passing all supplied // arguments to this function each listener. Event.prototype.dispatch = function(varargs) { - return this.dispatch_(Array.prototype.slice.call(arguments), undefined); + return this.dispatch_($Array.slice(arguments), undefined); }; // Detaches this event object from its name. @@ -396,7 +396,8 @@ // We remove the first parameter from the validation to give the user more // meaningful error messages. validate([rules, opt_cb], - ruleFunctionSchemas.addRules.parameters.slice().splice(1)); + $Array.splice( + $Array.slice(ruleFunctionSchemas.addRules.parameters), 1)); sendRequest("events.addRules", [this.eventName_, rules, opt_cb], ruleFunctionSchemas.addRules.parameters); } @@ -408,7 +409,8 @@ // We remove the first parameter from the validation to give the user more // meaningful error messages. validate([ruleIdentifiers, opt_cb], - ruleFunctionSchemas.removeRules.parameters.slice().splice(1)); + $Array.splice( + $Array.slice(ruleFunctionSchemas.removeRules.parameters), 1)); sendRequest("events.removeRules", [this.eventName_, ruleIdentifiers, opt_cb], ruleFunctionSchemas.removeRules.parameters); @@ -421,7 +423,8 @@ // We remove the first parameter from the validation to give the user more // meaningful error messages. validate([ruleIdentifiers, cb], - ruleFunctionSchemas.getRules.parameters.slice().splice(1)); + $Array.splice( + $Array.slice(ruleFunctionSchemas.getRules.parameters), 1)); sendRequest("events.getRules", [this.eventName_, ruleIdentifiers, cb], diff --git a/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js b/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js index 7903a3d..394f191f 100644 --- a/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js +++ b/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js @@ -45,8 +45,10 @@ binding.registerCustomHook( // We are making a copy of |arr|, but applying |func| to index 1. function validate(arr, func) { var newArr = []; - for (var i = 0; i < arr.length; i++) - newArr.push(i == 1 && typeof(arr) == 'object' ? func(arr[i]) : arr[i]); + for (var i = 0; i < arr.length; i++) { + $Array.push(newArr, + i == 1 && typeof(arr) == 'object' ? func(arr[i]) : arr[i]); + } return newArr; } diff --git a/chrome/renderer/resources/extensions/extension_custom_bindings.js b/chrome/renderer/resources/extensions/extension_custom_bindings.js index e1c03dc..3326e9b 100644 --- a/chrome/renderer/resources/extensions/extension_custom_bindings.js +++ b/chrome/renderer/resources/extensions/extension_custom_bindings.js @@ -80,7 +80,7 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { // Checking existence isn't enough since some functions are disabled via // getters that throw exceptions. Assume that any getter is such a function. if (chrome.runtime && - chrome.runtime.hasOwnProperty(alias) && + $Object.hasOwnProperty(chrome.runtime, alias) && chrome.runtime.__lookupGetter__(alias) === undefined) { extension[alias] = chrome.runtime[alias]; } diff --git a/chrome/renderer/resources/extensions/file_system_custom_bindings.js b/chrome/renderer/resources/extensions/file_system_custom_bindings.js index 50055b8..f66c20d 100644 --- a/chrome/renderer/resources/extensions/file_system_custom_bindings.js +++ b/chrome/renderer/resources/extensions/file_system_custom_bindings.js @@ -76,7 +76,7 @@ binding.registerCustomHook(function(bindingsAPI) { apiFunctions.setUpdateArgumentsPostValidate( functionName, function(fileEntry, callback) { var fileSystemName = fileEntry.filesystem.name; - var relativePath = fileEntry.fullPath.slice(1); + var relativePath = $String.slice(fileEntry.fullPath, 1); return [fileSystemName, relativePath, callback]; }); } @@ -93,7 +93,7 @@ binding.registerCustomHook(function(bindingsAPI) { if (!id) return ''; var fileSystemName = fileEntry.filesystem.name; - var relativePath = fileEntry.fullPath.slice(1); + var relativePath = $String.slice(fileEntry.fullPath, 1); sendRequest(this.name, [id, fileSystemName, relativePath], this.definition.parameters, {}); @@ -129,19 +129,19 @@ binding.registerCustomHook(function(bindingsAPI) { fileSystem.getWritableFileEntry = function() { console.log("chrome.fileSystem.getWritableFileEntry is deprecated"); console.log("Please use chrome.fileSystem.getWritableEntry instead"); - fileSystem.getWritableEntry.apply(this, arguments); + $Function.apply(fileSystem.getWritableEntry, this, arguments); }; fileSystem.isWritableFileEntry = function() { console.log("chrome.fileSystem.isWritableFileEntry is deprecated"); console.log("Please use chrome.fileSystem.isWritableEntry instead"); - fileSystem.isWritableEntry.apply(this, arguments); + $Function.apply(fileSystem.isWritableEntry, this, arguments); }; fileSystem.chooseFile = function() { console.log("chrome.fileSystem.chooseFile is deprecated"); console.log("Please use chrome.fileSystem.chooseEntry instead"); - fileSystem.chooseEntry.apply(this, arguments); + $Function.apply(fileSystem.chooseEntry, this, arguments); }; }); diff --git a/chrome/renderer/resources/extensions/i18n_custom_bindings.js b/chrome/renderer/resources/extensions/i18n_custom_bindings.js index a2f5869..ae8395b 100644 --- a/chrome/renderer/resources/extensions/i18n_custom_bindings.js +++ b/chrome/renderer/resources/extensions/i18n_custom_bindings.js @@ -13,7 +13,7 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setUpdateArgumentsPreValidate('getMessage', function() { - var args = Array.prototype.slice.call(arguments); + var args = $Array.slice(arguments); // The first argument is the message, and should be a string. var message = args[0]; diff --git a/chrome/renderer/resources/extensions/image_util.js b/chrome/renderer/resources/extensions/image_util.js index 7075c94..7986740 100644 --- a/chrome/renderer/resources/extensions/image_util.js +++ b/chrome/renderer/resources/extensions/image_util.js @@ -60,7 +60,7 @@ function on_complete_index(index, err, loading, finished, callbacks) { finished[index] = { width: width, height: height, data: imageData }; if (err) callbacks.onerror(index); - if (Object.keys(loading).length == 0) + if ($Object.keys(loading).length == 0) callbacks.oncomplete(finished); } } diff --git a/chrome/renderer/resources/extensions/json_schema.js b/chrome/renderer/resources/extensions/json_schema.js index 19d3634..c894ef2 100644 --- a/chrome/renderer/resources/extensions/json_schema.js +++ b/chrome/renderer/resources/extensions/json_schema.js @@ -167,18 +167,18 @@ JSONSchemaValidator.prototype.addTypes = function(typeOrTypeList) { JSONSchemaValidator.prototype.getAllTypesForSchema = function(schema) { var schemaTypes = []; if (schema.type) - schemaTypes.push(schema.type); + $Array.push(schemaTypes, schema.type); if (schema.choices) { for (var i = 0; i < schema.choices.length; i++) { var choiceTypes = this.getAllTypesForSchema(schema.choices[i]); - schemaTypes = schemaTypes.concat(choiceTypes); + schemaTypes = $Array.concat(schemaTypes, choiceTypes); } } var ref = schema['$ref']; if (ref) { var type = this.getOrAddType(ref); CHECK(type, 'Could not find type ' + ref); - schemaTypes = schemaTypes.concat(this.getAllTypesForSchema(type)); + schemaTypes = $Array.concat(schemaTypes, this.getAllTypesForSchema(type)); } return schemaTypes; }; @@ -341,7 +341,7 @@ JSONSchemaValidator.prototype.validateObject = // TODO(aa): If it ever turns out that we actually want this to work, // there are other checks we could put here, like requiring that schema // properties be objects that have a 'type' property. - if (!schema.properties.hasOwnProperty(prop)) + if (!$Object.hasOwnProperty(schema.properties, prop)) continue; var propPath = path ? path + "." + prop : prop; @@ -377,7 +377,7 @@ JSONSchemaValidator.prototype.validateObject = continue; // Any properties inherited through the prototype are ignored. - if (!instance.hasOwnProperty(prop)) + if (!$Object.hasOwnProperty(instance, prop)) continue; var propPath = path ? path + "." + prop : prop; @@ -502,7 +502,7 @@ JSONSchemaValidator.prototype.validateType = function(instance, schema, path) { * message. */ JSONSchemaValidator.prototype.addError = function(path, key, replacements) { - this.errors.push({ + $Array.push(this.errors, { path: path, message: JSONSchemaValidator.formatError(key, replacements) }); diff --git a/chrome/renderer/resources/extensions/last_error.js b/chrome/renderer/resources/extensions/last_error.js index 42e5dd8..7252a2e 100644 --- a/chrome/renderer/resources/extensions/last_error.js +++ b/chrome/renderer/resources/extensions/last_error.js @@ -54,7 +54,7 @@ function run(name, message, stack, callback, args) { var targetChrome = GetGlobal(callback).chrome; set(name, message, stack, targetChrome); try { - callback.apply(undefined, args); + $Function.apply(callback, undefined, args); } finally { clear(targetChrome); } diff --git a/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js b/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js index 93e0a34..e741fea 100644 --- a/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js +++ b/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js @@ -24,7 +24,7 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { for (var i = 0; i < response.length; i++) { var filesystem = mediaGalleriesNatives.GetMediaFileSystemObject( response[i].fsid); - result.push(filesystem); + $Array.push(result, filesystem); var metadata = response[i]; delete metadata.fsid; mediaGalleriesMetadata[filesystem.name] = metadata; diff --git a/chrome/renderer/resources/extensions/miscellaneous_bindings.js b/chrome/renderer/resources/extensions/miscellaneous_bindings.js index 52a7550..14b83ba 100644 --- a/chrome/renderer/resources/extensions/miscellaneous_bindings.js +++ b/chrome/renderer/resources/extensions/miscellaneous_bindings.js @@ -101,19 +101,19 @@ var errorMsg = []; var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest"; if (isSendMessage && !responseCallbackPreserved) { - errorMsg.push( + $Array.push(errorMsg, "The chrome." + eventName + " listener must return true if you " + "want to send a response after the listener returns"); } else { - errorMsg.push( + $Array.push(errorMsg, "Cannot send a response more than once per chrome." + eventName + " listener per document"); } - errorMsg.push("(message was sent by extension" + sourceExtensionId); + $Array.push(errorMsg, "(message was sent by extension" + sourceExtensionId); if (sourceExtensionId != "" && sourceExtensionId != targetExtensionId) - errorMsg.push("for extension " + targetExtensionId); + $Array.push(errorMsg, "for extension " + targetExtensionId); if (sourceUrl != "") - errorMsg.push("for URL " + sourceUrl); + $Array.push(errorMsg, "for URL " + sourceUrl); lastError.set(eventName, errorMsg.join(" ") + ").", null, chrome); } @@ -318,7 +318,7 @@ // schema validation is expecting, e.g. // extension.sendRequest(req) -> extension.sendRequest(null, req) // extension.sendRequest(req, cb) -> extension.sendRequest(null, req, cb) - var args = Array.prototype.splice.call(arguments, 1); // skip functionName + var args = $Array.splice(arguments, 1); // skip functionName var lastArg = args.length - 1; // responseCallback (last argument) is optional. diff --git a/chrome/renderer/resources/extensions/notifications_custom_bindings.js b/chrome/renderer/resources/extensions/notifications_custom_bindings.js index fb19ac4..5150a4f 100644 --- a/chrome/renderer/resources/extensions/notifications_custom_bindings.js +++ b/chrome/renderer/resources/extensions/notifications_custom_bindings.js @@ -36,7 +36,7 @@ function replaceNotificationOptionURLs(notification_details, callback) { // |imageUrl| is optional. if (notification_details.imageUrl) { - url_specs.push({ + $Array.push(url_specs, { path: notification_details.imageUrl, width: 360, height: 540, @@ -50,7 +50,7 @@ function replaceNotificationOptionURLs(notification_details, callback) { var num_buttons = button_list.length; for (var i = 0; i < num_buttons; i++) { if (button_list[i].iconUrl) { - url_specs.push({ + $Array.push(url_specs, { path: button_list[i].iconUrl, width: 16, height: 16, diff --git a/chrome/renderer/resources/extensions/omnibox_custom_bindings.js b/chrome/renderer/resources/extensions/omnibox_custom_bindings.js index 2fd7a6c..6e753a9 100644 --- a/chrome/renderer/resources/extensions/omnibox_custom_bindings.js +++ b/chrome/renderer/resources/extensions/omnibox_custom_bindings.js @@ -65,7 +65,7 @@ function parseOmniboxDescription(input) { 'type': child.nodeName, 'offset': result.description.length }; - result.descriptionStyles.push(style); + $Array.push(result.descriptionStyles, style); walk(child); style.length = result.description.length - style.offset; continue; @@ -105,7 +105,7 @@ binding.registerCustomHook(function(bindingsAPI) { var parseResult = parseOmniboxDescription( userSuggestions[i].description); parseResult.content = userSuggestions[i].content; - suggestions.push(parseResult); + $Array.push(suggestions, parseResult); } return [requestId, suggestions]; }); diff --git a/chrome/renderer/resources/extensions/permissions_custom_bindings.js b/chrome/renderer/resources/extensions/permissions_custom_bindings.js index 7ff85f5..244fd95 100644 --- a/chrome/renderer/resources/extensions/permissions_custom_bindings.js +++ b/chrome/renderer/resources/extensions/permissions_custom_bindings.js @@ -21,7 +21,7 @@ binding.registerCustomHook(function(api) { var permissions = api.compiledApi; function maybeConvertToObject(str) { - var parts = str.split('|'); + var parts = $String.split(str, '|'); if (parts.length != 2) return str; @@ -41,7 +41,7 @@ binding.registerCustomHook(function(api) { for (var i = 0; i < args.length; i += 1) { if (typeof(args[i]) == 'object') { var a = args[i]; - var keys = Object.keys(a); + var keys = $Object.keys(a); if (keys.length != 1) { throw new Error("Too many keys in object-style permission."); } @@ -75,7 +75,7 @@ binding.registerCustomHook(function(api) { // that handleResponse doesn't call it again. try { if (request.callback) - request.callback.apply(request, [response]); + $Function.apply(request.callback, request, [response]); } finally { delete request.callback; } diff --git a/chrome/renderer/resources/extensions/platform_app.js b/chrome/renderer/resources/extensions/platform_app.js index 607ea8b..78a13ff 100644 --- a/chrome/renderer/resources/extensions/platform_app.js +++ b/chrome/renderer/resources/extensions/platform_app.js @@ -134,5 +134,5 @@ Window.prototype.addEventListener = function(type) { if (type === 'unload' || type === 'beforeunload') generateDisabledMethodStub(type)(); else - return windowAddEventListener.apply(window, arguments); + return $Function.apply(windowAddEventListener, window, arguments); }; diff --git a/chrome/renderer/resources/extensions/schema_utils.js b/chrome/renderer/resources/extensions/schema_utils.js index 5ec93fc..d54fbe2 100644 --- a/chrome/renderer/resources/extensions/schema_utils.js +++ b/chrome/renderer/resources/extensions/schema_utils.js @@ -44,11 +44,11 @@ function getSignatures(parameterSchemas) { if (parameterSchemas.length === 0) return [[]]; var signatures = []; - var remaining = getSignatures(parameterSchemas.slice(1)); + var remaining = getSignatures($Array.slice(parameterSchemas, 1)); for (var i = 0; i < remaining.length; i++) - signatures.push([parameterSchemas[0]].concat(remaining[i])) + $Array.push(signatures, $Array.concat([parameterSchemas[0]], remaining[i])) if (parameterSchemas[0].optional) - return signatures.concat(remaining); + return $Array.concat(signatures, remaining); return signatures; }; @@ -119,9 +119,9 @@ function normalizeArgumentsAndValidate(args, funDef) { var ai = 0; for (var si = 0; si < definedSignature.length; si++) { if (definedSignature[si] === resolvedSignature[ai]) - normalizedArgs.push(args[ai++]); + $Array.push(normalizedArgs, args[ai++]); else - normalizedArgs.push(null); + $Array.push(normalizedArgs, null); } return normalizedArgs; }; diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js index c4083c6..f08d770 100644 --- a/chrome/renderer/resources/extensions/searchbox_api.js +++ b/chrome/renderer/resources/extensions/searchbox_api.js @@ -100,7 +100,7 @@ if (!chrome.embeddedSearch) { } var dedupedResults = []; for (url in urlToResultMap) { - dedupedResults.push(urlToResultMap[url]); + $Array.push(dedupedResults, urlToResultMap[url]); } return dedupedResults; } diff --git a/chrome/renderer/resources/extensions/send_request.js b/chrome/renderer/resources/extensions/send_request.js index 1e203ca..28798ba 100644 --- a/chrome/renderer/resources/extensions/send_request.js +++ b/chrome/renderer/resources/extensions/send_request.js @@ -18,7 +18,7 @@ var calledSendRequest = false; // Runs a user-supplied callback safely. function safeCallbackApply(name, request, callback, args) { try { - callback.apply(request, args); + $Function.apply(callback, request, args); } catch (e) { var errorMessage = "Error in response to " + name + ": " + e; if (request.stack && request.stack != '') @@ -44,7 +44,7 @@ function handleResponse(requestId, name, success, responseList, error) { if (request.callback) { var chromeForCallback = natives.GetGlobal(request.callback).chrome; if (chromeForCallback != chrome) - chromesForLastError.push(chromeForCallback); + $Array.push(chromesForLastError, chromeForCallback); } $Array.forEach(chromesForLastError, function(c) {lastError.clear(c)}); @@ -60,7 +60,7 @@ function handleResponse(requestId, name, success, responseList, error) { safeCallbackApply(name, request, request.customCallback, - [name, request].concat(responseList)); + $Array.concat([name, request], responseList)); } if (request.callback) { @@ -82,7 +82,7 @@ function handleResponse(requestId, name, success, responseList, error) { }; function getExtensionStackTrace(call_name) { - var stack = new Error().stack.split('\n'); + var stack = $String.split(new Error().stack, '\n'); // Remove stack frames before and after that weren't associated with the // extension. diff --git a/chrome/renderer/resources/extensions/storage_area.js b/chrome/renderer/resources/extensions/storage_area.js index 0749602..66d57d4 100644 --- a/chrome/renderer/resources/extensions/storage_area.js +++ b/chrome/renderer/resources/extensions/storage_area.js @@ -7,7 +7,7 @@ var normalizeArgumentsAndValidate = var sendRequest = require('sendRequest').sendRequest; function extendSchema(schema) { - var extendedSchema = schema.slice(); + var extendedSchema = $Array.slice(schema); extendedSchema.unshift({'type': 'string'}); return extendedSchema; } @@ -24,11 +24,11 @@ function StorageArea(namespace, schema) { function bindApiFunction(functionName) { self[functionName] = function() { var funSchema = this.functionSchemas[functionName]; - var args = Array.prototype.slice.call(arguments); + var args = $Array.slice(arguments); args = normalizeArgumentsAndValidate(args, funSchema); return sendRequest( 'storage.' + functionName, - [namespace].concat(args), + $Array.concat([namespace], args), extendSchema(funSchema.definition.parameters), {preserveNullInObjects: true}); }; diff --git a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js index 6ada6a7..c2df0b0 100644 --- a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js +++ b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js @@ -29,7 +29,7 @@ binding.registerCustomHook(function(bindingsAPI) { functionName, function(entries, callback) { var fileSystemUrlArray = []; for (var i=0; i < entries.length; i++) { - fileSystemUrlArray.push(entries[i].toURL()); + $Array.push(fileSystemUrlArray, entries[i].toURL()); } return [fileSystemUrlArray, callback]; }); @@ -76,7 +76,7 @@ binding.registerCustomHook(function(bindingsAPI) { entry.isDirectory); result.status = response[i].status; result.error = response[i].error; - results.push(result); + $Array.push(results, result); } } if (request.callback) diff --git a/chrome/renderer/resources/extensions/test_custom_bindings.js b/chrome/renderer/resources/extensions/test_custom_bindings.js index ad0bd25..231e339 100644 --- a/chrome/renderer/resources/extensions/test_custom_bindings.js +++ b/chrome/renderer/resources/extensions/test_custom_bindings.js @@ -61,8 +61,10 @@ binding.registerCustomHook(function(api) { var redundantPrefix = 'Error\n'; chrome.test.fail( 'Callback has already been run. ' + - 'First call:\n' + called.slice(redundantPrefix.length) + '\n' + - 'Second call:\n' + new Error().stack.slice(redundantPrefix.length)); + 'First call:\n' + + $String.slice(called, redundantPrefix.length) + '\n' + + 'Second call:\n' + + $String.slice(new Error().stack, redundantPrefix.length)); } called = new Error().stack; @@ -151,12 +153,16 @@ binding.registerCustomHook(function(api) { return false; for (var p in actual) { - if (actual.hasOwnProperty(p) && !expected.hasOwnProperty(p)) + if ($Object.hasOwnProperty(actual, p) && + !$Object.hasOwnProperty(expected, p)) { return false; + } } for (var p in expected) { - if (expected.hasOwnProperty(p) && !actual.hasOwnProperty(p)) + if ($Object.hasOwnProperty(expected, p) && + !$Object.hasOwnProperty(actual, p)) { return false; + } } for (var p in expected) { @@ -225,7 +231,7 @@ binding.registerCustomHook(function(api) { function safeFunctionApply(func, args) { try { if (func) - func.apply(null, args); + $Function.apply(func, null, args); } catch (e) { var msg = "uncaught exception " + e; chromeTest.fail(msg); diff --git a/chrome/renderer/resources/extensions/unload_event.js b/chrome/renderer/resources/extensions/unload_event.js index 85a5465..52cf889 100644 --- a/chrome/renderer/resources/extensions/unload_event.js +++ b/chrome/renderer/resources/extensions/unload_event.js @@ -11,13 +11,13 @@ var listeners = []; exports.addListener = function(listener) { - listeners.push(listener); + $Array.push(listeners, listener); }; exports.removeListener = function(listener) { for (var i = 0; i < listeners.length; ++i) { if (listeners[i] == listener) { - listeners.splice(i, 1); + $Array.splice(listeners, i, 1); return; } } diff --git a/chrome/renderer/resources/extensions/utils.js b/chrome/renderer/resources/extensions/utils.js index 45d9295..80b5f1b 100644 --- a/chrome/renderer/resources/extensions/utils.js +++ b/chrome/renderer/resources/extensions/utils.js @@ -32,7 +32,7 @@ function lookup(array_of_dictionaries, field, value) { } function loadTypeSchema(typeName, defaultSchema) { - var parts = typeName.split('.'); + var parts = $String.split(typeName, '.'); if (parts.length == 1) { if (defaultSchema == null) { WARNING('Trying to reference "' + typeName + '" ' + @@ -41,7 +41,7 @@ function loadTypeSchema(typeName, defaultSchema) { } var types = defaultSchema.types; } else { - var schemaName = parts.slice(0, parts.length - 1).join('.') + var schemaName = $Array.join($Array.slice(parts, 0, parts.length - 1), '.'); var types = schemaRegistry.GetSchema(schemaName).types; } for (var i = 0; i < types.length; ++i) { diff --git a/chrome/renderer/resources/extensions/web_request_custom_bindings.js b/chrome/renderer/resources/extensions/web_request_custom_bindings.js index 6e2bac08..045fe96 100644 --- a/chrome/renderer/resources/extensions/web_request_custom_bindings.js +++ b/chrome/renderer/resources/extensions/web_request_custom_bindings.js @@ -12,7 +12,7 @@ binding.registerCustomHook(function(api) { var apiFunctions = api.apiFunctions; apiFunctions.setHandleRequest('handlerBehaviorChanged', function() { - var args = Array.prototype.slice.call(arguments); + var args = $Array.slice(arguments); sendRequest(this.name, args, this.definition.parameters, {forIOThread: true}); }); diff --git a/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js b/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js index 45ebec2..7d16805 100644 --- a/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js +++ b/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js @@ -67,7 +67,7 @@ WebRequestEvent.prototype.addListener = var subEventName = webRequestNatives.GetUniqueSubEventName(this.eventName_); // Note: this could fail to validate, in which case we would not add the // subEvent listener. - validate(Array.prototype.slice.call(arguments, 1), this.extraArgSchemas_); + validate($Array.slice(arguments, 1), this.extraArgSchemas_); webRequestInternal.addEventListener( cb, opt_filter, opt_extraInfo, this.eventName_, subEventName, this.webViewInstanceId_); @@ -79,7 +79,7 @@ WebRequestEvent.prototype.addListener = subEventCallback = function() { var requestId = arguments[0].requestId; try { - var result = cb.apply(null, arguments); + var result = $Function.apply(cb, null, arguments); webRequestInternal.eventHandled( eventName, subEventName, requestId, result); } catch (e) { @@ -97,10 +97,10 @@ WebRequestEvent.prototype.addListener = webRequestInternal.eventHandled( eventName, subEventName, requestId, response); }; - cb.apply(null, [details, handledCallback]); + $Function.apply(cb, null, [details, handledCallback]); }; } - this.subEvents_.push( + $Array.push(this.subEvents_, {subEvent: subEvent, callback: cb, subEventCallback: subEventCallback}); subEvent.addListener(subEventCallback); }; @@ -117,7 +117,7 @@ WebRequestEvent.prototype.removeListener = function(cb) { console.error( 'Internal error: webRequest subEvent has orphaned listeners.'); } - this.subEvents_.splice(idx, 1); + $Array.splice(this.subEvents_, idx, 1); } }; @@ -156,13 +156,13 @@ binding.registerCustomHook(function(api) { var apiFunctions = api.apiFunctions; apiFunctions.setHandleRequest('addEventListener', function() { - var args = Array.prototype.slice.call(arguments); + var args = $Array.slice(arguments); sendRequest(this.name, args, this.definition.parameters, {forIOThread: true}); }); apiFunctions.setHandleRequest('eventHandled', function() { - var args = Array.prototype.slice.call(arguments); + var args = $Array.slice(arguments); sendRequest(this.name, args, this.definition.parameters, {forIOThread: true}); }); diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js index 1e19344..75b05fb 100644 --- a/chrome/renderer/resources/extensions/web_view.js +++ b/chrome/renderer/resources/extensions/web_view.js @@ -138,7 +138,7 @@ WebView.prototype.setupWebviewNodeMethods_ = function() { var self = this; $Array.forEach(WEB_VIEW_API_METHODS, function(apiMethod) { self.webviewNode_[apiMethod] = function(var_args) { - return self.browserPluginNode_[apiMethod].apply( + return $Function.apply(self.browserPluginNode_[apiMethod], self.browserPluginNode_, arguments); }; }, this); @@ -388,15 +388,15 @@ WebView.prototype.setupExecuteCodeAPI_ = function() { this.webviewNode_['executeScript'] = function(var_args) { validateCall(); - var args = [self.browserPluginNode_.getGuestInstanceId()].concat( - Array.prototype.slice.call(arguments)); - chrome.webview.executeScript.apply(null, args); + var args = $Array.concat([self.browserPluginNode_.getGuestInstanceId()], + $Array.slice(arguments)); + $Function.apply(chrome.webview.executeScript, null, args); } this.webviewNode_['insertCSS'] = function(var_args) { validateCall(); - var args = [self.browserPluginNode_.getGuestInstanceId()].concat( - Array.prototype.slice.call(arguments)); - chrome.webview.insertCSS.apply(null, args); + var args = $Array.concat([self.browserPluginNode_.getGuestInstanceId()], + $Array.slice(arguments)); + $Function.apply(chrome.webview.insertCSS, null, args); } }; diff --git a/chrome/test/data/extensions/api_test/messaging/externally_connectable/sites/assertions.js b/chrome/test/data/extensions/api_test/messaging/externally_connectable/sites/assertions.js index 0470222..3f58051 100644 --- a/chrome/test/data/extensions/api_test/messaging/externally_connectable/sites/assertions.js +++ b/chrome/test/data/extensions/api_test/messaging/externally_connectable/sites/assertions.js @@ -4,6 +4,62 @@ window.assertions = (function() { +// We are going to kill all of the builtins, so hold onto the ones we need. +var defineGetter = Object.prototype.__defineGetter__; +var defineSetter = Object.prototype.__defineSetter__; +var Error = window.Error; +var forEach = Array.prototype.forEach; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var getOwnPropertyNames = Object.getOwnPropertyNames; +var stringify = JSON.stringify; + +// Kill all of the builtins functions to give us a fairly high confidence that +// the environment our bindings run in can't interfere with our code. +// These are taken from the ECMAScript spec. +var builtinTypes = [ + Object, Function, Array, String, Boolean, Number, Math, Date, RegExp, JSON, +]; + +function clobber(obj, name, qualifiedName) { + // Clobbering constructors would break everything. + // Clobbering toString is annoying. + // Clobbering __proto__ breaks in ways that grep can't find. + // Clobbering Function.call would make it impossible to implement these tests. + // Clobbering Object.valueOf breaks v8. + if (name == 'constructor' || + name == 'toString' || + name == '__proto__' || + qualifiedName == 'Function.call' || + qualifiedName == 'Object.valueOf') { + return; + } + if (typeof(obj[name]) == 'function') { + obj[name] = function() { + throw new Error('Clobbered ' + qualifiedName + ' function'); + }; + } else { + defineGetter.call(obj, name, function() { + throw new Error('Clobbered ' + qualifiedName + ' getter'); + }); + } +} + +forEach.call(builtinTypes, function(builtin) { + var prototype = builtin.prototype; + var typename = '<unknown>'; + if (prototype) { + typename = prototype.constructor.name; + forEach.call(getOwnPropertyNames(prototype), function(name) { + clobber(prototype, name, typename + '.' + name); + }); + } + forEach.call(getOwnPropertyNames(builtin), function(name) { + clobber(builtin, name, typename + '.' + name); + }); + if (builtin.name) + clobber(window, builtin.name, 'window.' + builtin.name); +}); + // Codes for test results. Must match ExternallyConnectableMessagingTest::Result // in c/b/extensions/extension_messages_apitest.cc. var results = { @@ -37,7 +93,7 @@ function checkResponse(response, reply) { // // First check the sender was correct. var incorrectSender = false; - if (!response.sender.hasOwnProperty('tab')) { + if (!hasOwnProperty.call(response.sender, 'tab')) { console.warn('Expected a tab, got none'); incorrectSender = true; } @@ -46,7 +102,7 @@ function checkResponse(response, reply) { response.sender.tab.url); incorrectSender = true; } - if (response.sender.hasOwnProperty('id')) { + if (hasOwnProperty.call(response.sender, 'id')) { console.warn('Expected no id, got "' + response.sender.id + '"'); incorrectSender = true; } @@ -61,8 +117,8 @@ function checkResponse(response, reply) { } // Check the correct content was echoed. - var expectedJson = JSON.stringify(message); - var actualJson = JSON.stringify(response.message); + var expectedJson = stringify(message); + var actualJson = stringify(response.message); if (actualJson == expectedJson) return true; console.warn('Expected message ' + expectedJson + ' got ' + actualJson); @@ -70,7 +126,9 @@ function checkResponse(response, reply) { return false; } -var sendToBrowser = domAutomationController.send.bind(domAutomationController); +function sendToBrowser(msg) { + domAutomationController.send(msg); +} return { canConnectAndSendMessages: function(extensionId) { @@ -120,7 +178,7 @@ return { areAnyRuntimePropertiesDefined: function(names) { var result = false; if (chrome.runtime) { - names.forEach(function(name) { + forEach.call(names, function(name) { if (chrome.runtime[name]) { console.log('runtime.' + name + ' is defined'); result = true; |