Además de redefinir console._commandLineAPI
, hay otras formas de entrar en InjectedScriptHost en los navegadores WebKit, para evitar o alterar la evaluación de las expresiones ingresadas en la consola del desarrollador.
Editar:
Chrome ha solucionado esto en una versión anterior. - que debe haber sido antes de febrero de 2015, ya que creé la esencia en ese momento
Así que aquí hay otra posibilidad. Esta vez nos conectamos, un nivel por encima, directamente en InjectedScript
lugar de InjectedScriptHost
oponernos a la versión anterior.
Lo cual es bastante bueno, ya que puedes usar el parche directamente en InjectedScript._evaluateAndWrap
lugar de tener que confiar, InjectedScriptHost.evaluate
ya que eso te da un control más preciso sobre lo que debería suceder.
Otra cosa bastante interesante es que podemos interceptar el resultado interno cuando se evalúa una expresión y devolverla al usuario en lugar del comportamiento normal.
Aquí está el código, que hace exactamente eso, devuelve el resultado interno cuando un usuario evalúa algo en la consola.
var is;
Object.defineProperty(Object.prototype,"_lastResult",{
get:function(){
return this._lR;
},
set:function(v){
if (typeof this._commandLineAPIImpl=="object") is=this;
this._lR=v;
}
});
setTimeout(function(){
var ev=is._evaluateAndWrap;
is._evaluateAndWrap=function(){
var res=ev.apply(is,arguments);
console.log();
if (arguments[2]==="completion") {
//This is the path you end up when a user types in the console and autocompletion get's evaluated
//Chrome expects a wrapped result to be returned from evaluateAndWrap.
//You can use `ev` to generate an object yourself.
//In case of the autocompletion chrome exptects an wrapped object with the properties that can be autocompleted. e.g.;
//{iGetAutoCompleted: true}
//You would then go and return that object wrapped, like
//return ev.call (is, '', '({test:true})', 'completion', true, false, true);
//Would make `test` pop up for every autocompletion.
//Note that syntax as well as every Object.prototype property get's added to that list later,
//so you won't be able to exclude things like `while` from the autocompletion list,
//unless you wou'd find a way to rewrite the getCompletions function.
//
return res; //Return the autocompletion result. If you want to break that, return nothing or an empty object
} else {
//This is the path where you end up when a user actually presses enter to evaluate an expression.
//In order to return anything as normal evaluation output, you have to return a wrapped object.
//In this case, we want to return the generated remote object.
//Since this is already a wrapped object it would be converted if we directly return it. Hence,
//`return result` would actually replicate the very normal behaviour as the result is converted.
//to output what's actually in the remote object, we have to stringify it and `evaluateAndWrap` that object again.`
//This is quite interesting;
return ev.call (is, null, '(' + JSON.stringify (res) + ')', "console", true, false, true)
}
};
},0);
Es un poco detallado, pero pensé ponerle algunos comentarios
Entonces, normalmente, si un usuario, por ejemplo, evalúa [1,2,3,4]
, esperaría el siguiente resultado:
Después de que monkeypatching InjectedScript._evaluateAndWrap
evalúa la misma expresión, da el siguiente resultado:
Como puede ver, la pequeña flecha izquierda, que indica la salida, todavía está allí, pero esta vez obtenemos un objeto. Donde el resultado de la expresión, la matriz [1,2,3,4]
se representa como un objeto con todas sus propiedades descritas.
Recomiendo tratar de evaluar esta y aquella expresión, incluidas las que generan errores. Es bastante interesante.
Además, echa un vistazo a la is
- InjectedScriptHost
- objeto. Proporciona algunos métodos para jugar y obtener un poco de información sobre los aspectos internos del inspector.
Por supuesto, puede interceptar toda esa información y aún así devolver el resultado original al usuario.
Simplemente reemplace la declaración de retorno en la ruta else por una console.log (res)
siguiente a return res
. Entonces terminarías con lo siguiente.
Fin de Editar
Esta es la versión anterior que fue corregida por Google. Por lo tanto, ya no es posible.
Uno de ellos está enganchado Function.prototype.call
Chrome evalúa la expresión ingresada al call
usar su función eval con InjectedScriptHost
asthisArg
var result = evalFunction.call(object, expression);
Teniendo en cuenta esto, se puede escuchar a la thisArg
del call
ser evaluate
y obtener una referencia al primer argumento ( InjectedScriptHost
)
if (window.URL) {
var ish, _call = Function.prototype.call;
Function.prototype.call = function () { //Could be wrapped in a setter for _commandLineAPI, to redefine only when the user started typing.
if (arguments.length > 0 && this.name === "evaluate" && arguments [0].constructor.name === "InjectedScriptHost") { //If thisArg is the evaluate function and the arg0 is the ISH
ish = arguments[0];
ish.evaluate = function (e) { //Redefine the evaluation behaviour
throw new Error ('Rejected evaluation of: \n\'' + e.split ('\n').slice(1,-1).join ("\n") + '\'');
};
Function.prototype.call = _call; //Reset the Function.prototype.call
return _call.apply(this, arguments);
}
};
}
Podría, por ejemplo, arrojar un error, que la evaluación fue rechazada.
Aquí hay un ejemplo donde la expresión ingresada se pasa a un compilador CoffeeScript antes de pasarla a la evaluate
función.