0

Clean up DevTools API docs following removal of old APIs

- remove docs for chrome.experimental.devtools.console
- remove docs and sample for preprocessorScript option of
    chrome.devtools.inspectedWindow.reload()

BUG=602063

Review-Url: https://codereview.chromium.org/2179673002
Cr-Commit-Position: refs/heads/master@{#408525}
This commit is contained in:
caseq
2016-07-28 17:06:29 -07:00
committed by Commit bot
parent a1f9528dfa
commit 12958cac93
14 changed files with 11 additions and 444 deletions

@ -1,100 +0,0 @@
// Copyright (c) 2012 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.
[
{
"namespace": "experimental.devtools.console",
"description": "Use the <code>chrome.experimental.devtools.console</code> API to retrieve messages from the inspected page console and post messages there.",
"nocompile": true,
"functions": [
{
"name": "addMessage",
"type": "function",
"description": "Adds a message to the console.",
"parameters": [
{ "name": "severity", "$ref": "Severity", "description": "The severity of the message." },
{ "name": "text", "type": "string", "description": "The text of the message." }
]
},
{
"name": "getMessages",
"type": "function",
"description": "Retrieves console messages.",
"parameters": [
{
"name": "callback",
"type": "function",
"description": "A function that receives console messages when the request completes.",
"parameters": [
{
"name": "messages",
"type": "array",
"items": { "$ref": "ConsoleMessage" },
"description": "Console messages."
}
]
}
]
}
],
"types": [
{
"id": "ConsoleMessage",
"type": "object",
"description": "A console message.",
"properties": {
"severity": {
"$ref": "Severity",
"description": "Message severity."
},
"text": {
"type": "string",
"description": "The text of the console message, as represented by the first argument to the console.log() or a similar method (no parameter substitution performed)."
},
"url": {
"type": "string",
"optional": true,
"description": "The URL of the script that originated the message, if available."
},
"line": {
"type": "number",
"optional": true,
"description": "The number of the line where the message originated, if available."
}
}
},
{
"id": "Severity",
"type": "object",
"properties": {
"Tip": {
"type": "string"
},
"Debug": {
"type": "string"
},
"Log": {
"type": "string"
},
"Warning": {
"type": "string"
},
"Error": {
"type": "string"
}
}
}
],
"events": [
{
"name": "onMessageAdded",
"type": "function",
"description": "Fired when a new message is added to the console.",
"parameters": [
{ "name": "message", "$ref": "ConsoleMessage" }
]
}
]
}
]

@ -190,12 +190,6 @@
"type": "string",
"optional": true,
"description": "If specified, the script will be injected into every frame of the inspected page immediately upon load, before any of the frame's scripts. The script will not be injected after subsequent reloads&mdash;for example, if the user presses Ctrl+R."
},
"preprocessorScript": {
"type": "string",
"deprecated": "Please avoid using this parameter, it will be removed soon.",
"optional": true,
"description": "If specified, this script evaluates into a function that accepts three string arguments: the source to preprocess, the URL of the source, and a function name if the source is an DOM event handler. The preprocessorerScript function should return a string to be compiled by Chrome in place of the input source. In the case that the source is a DOM event handler, the returned source must compile to a single JS function."
}
}
}

@ -1,53 +0,0 @@
// Copyright 2013 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.
/** @fileoverview The chrome.devtools API does not support notifications from
* within a Web page nor does it report on events occuring in the page. For now
* we poll the page to determine a reasonable time to report the scripts.
*/
(function() {
/*
* @param {function} Called after the 'load' event on the inspected window
* @return {function} A function to be injected into the inspected window.
*/
function LoadMonitor(onLoadedCallback) {
function checkForLoad() {
var expr = 'window.__inspectedWindowLoaded';
function onEval(isLoaded, isException) {
if (isException)
throw new Error('Eval failed for ' + expr, isException.value);
if (isLoaded)
onLoadedCallback();
else
pollForLoad();
}
chrome.devtools.inspectedWindow.eval(expr, onEval);
}
function pollForLoad() {
setTimeout(checkForLoad, 200);
}
pollForLoad();
}
LoadMonitor.prototype = {
// This function should be converted to a string and run in the Web page
injectedScript: function() {
// Initialize a secret data structure.
window.__inspectedWindowLoaded = false;
window.addEventListener('load', function() {
window.__inspectedWindowLoaded = true;
console.log('loaded');
});
}
};
window.InspectedWindow = window.InspectedWindow || {};
InspectedWindow.LoadMonitor = LoadMonitor;
})();

@ -1,22 +0,0 @@
/* Copyright 2013 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. */
.newspaper {
font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif;
}
ol.newspaper {
border: 1px solid #69c;
font-size: 12px;
margin: 20px;
text-align: left;
width: 480px;
}
ol.newspaper li {
border-top: 1px dashed #fff;
color: #669;
padding: 5px;
vertical-align: top;
}

@ -1,14 +0,0 @@
<html>
<head>
<link rel='stylesheet' href='PreprocessorPanel.css'>
</head>
<body>
<button class='reload-button'>Reload</button>
<h2 class='newspaper' align="bottom">JavaScript files seen by devtools preprocessor. </h2>
<ol class='newspaper js-preprocessed-urls'>
<li>Reload to preprocess sources</li>
</ol>
<script src="InspectedWindowLoadMonitor.js"></script>
<script src="PreprocessorPanel.js"></script>
</body>
</html>

@ -1,68 +0,0 @@
// Copyright 2013 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.
(function() {
// This function is converted to a string and becomes the preprocessor
function preprocessor(source, url, listenerName) {
url = url ? url : '(eval)';
url += listenerName ? '_' + listenerName : '';
var prefix = 'window.__preprocessed = window.__preprocessed || [];\n';
prefix += 'window.__preprocessed.push(\'' + url +'\');\n';
var postfix = '\n//# sourceURL=' + url + '.js\n';
return prefix + source + postfix;
}
function extractPreprocessedFiles(onExtracted) {
var expr = 'window.__preprocessed';
function onEval(files, isException) {
if (isException)
throw new Error('Eval failed for ' + expr, isException.value);
onExtracted(files);
}
chrome.devtools.inspectedWindow.eval(expr, onEval);
}
function reloadWithPreprocessor(injectedScript) {
var options = {
ignoreCache: true,
userAgent: undefined,
injectedScript: '(' + injectedScript + ')()',
preprocessingScript: '(' + preprocessor + ')'
};
chrome.devtools.inspectedWindow.reload(options);
}
function demoPreprocessor() {
function onLoaded() {
extractPreprocessedFiles(updateUI);
}
var loadMonitor = new InspectedWindow.LoadMonitor(onLoaded);
reloadWithPreprocessor(loadMonitor.injectedScript);
}
function listen() {
var reloadButton = document.querySelector('.reload-button');
reloadButton.addEventListener('click', demoPreprocessor);
}
window.addEventListener('load', listen);
function createRow(url) {
var li = document.createElement('li');
li.textContent = url;
return li;
}
function updateUI(preprocessedFiles) {
var rowContainer = document.querySelector('.js-preprocessed-urls');
rowContainer.innerHTML = '';
preprocessedFiles.forEach(function(url) {
rowContainer.appendChild(createRow(url));
});
}
})();

@ -1,5 +0,0 @@
<html>
<body>
<script src="chrome-preprocessor.js"></script>
</body>
</html>

@ -1,10 +0,0 @@
// Copyright 2013 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.
chrome.devtools.panels.create(
'Preprocessor',
null, // No icon path
'Panel/PreprocessorPanel.html',
null // no callback needed
);

@ -1,12 +0,0 @@
{
"name": "Chrome Preprocessor Example",
"version": "0.1",
"description": "Simple hello-world example for chrome.devtools.inspectedWindow.reload() using preprocessor.",
"devtools_page": "chrome-preprocessor.html",
"manifest_version": 2,
"content_security_policy": "default-src 'self' chrome-extension-resource: ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval'; connect-src *; frame-src *;",
"web_accessible_resources":
[
"*"
]
}

@ -0,0 +1 @@
{{+partials.standard_extensions_article article:articles.experimental_devtools_console/}}

@ -36,10 +36,11 @@ loaded:</p>
<pre>
chrome.devtools.network.onRequestFinished.addListener(
function(request) {
if (request.response.bodySize > 40*1024)
chrome.experimental.devtools.console.addMessage(
chrome.experimental.devtools.console.Severity.Warning,
"Large image: " + request.request.url);
if (request.response.bodySize > 40*1024) {
chrome.devtools.inspectedWindow.eval(
'console.log("Large image: " + unescape("' +
escape(request.request.url) + '"))');
}
});
</pre>

@ -1,7 +1,6 @@
<p>
Use <code>chrome.experimental.devtools.console</code> to retrieve messages from
the inspected page console and post messages there. <code>getMessages()</code>
returns the list of messages on the console, <code>onMessageAdded</code>
event provides notifications on new messages, and <code>addMessage()</code>
allows an extension to add new messages.
</p>
The <code>chrome.experimental.devtools.console</code> experimental API
is no longer available. Consider using
<code>chrome.detvools.inspectedWindow.eval()</code> in conjunction with
<code>console.log()</code> to add messages to console.
</p>

@ -1 +0,0 @@
{{+partials.standard_extensions_api api:apis.extensions.devtools/experimental_console intro:intros.experimental_devtools_console/}}

@ -1,143 +0,0 @@
# Using the Chrome Devtools JavaScript preprocessing feature
The Chrome Devtools JavaScript preprocessor intercepts JavaScript just before it
enters V8, the Chrome JS system, allowing the JS to be transcoded before
compilation. In combination with page injected JavaScript, the preprocessor
allows a complete synthetic runtime to be constructed in JavaScript. Combined
with other functions in the `chrome.devtools` extension API, the preprocessor
allows new more sophisticated JavaScript-related developer tools to be created.
## API
To use the script preprocessor, write a
[chrome devtools extension](http://developer.chrome.com/extensions/devtools.inspectedWindow.html#method-reload)
that reloads the Web page with the preprocessor installed:
```javascript
chrome.devtools.inspectedWindow.reload({
ignoreCache: true,
injectedScript: runThisFirst,
preprocessorScript: preprocessor
});
```
where `preprocessorScript` is source code (string) for a JavaScript function
taking three string arguments, the source to preprocess, the URL of the source,
and a function name if the source is an DOM event handler. The
`preprocessorerScript` function should return a string to be compiled by Chrome
in place of the input source. In the case that the source is a DOM event
handler, the returned source must compile to a single JS function.
The
[Chrome Preprocessor Example](http://developer.chrome.com/extensions/samples.html)
illustrates the API call in a simple chrome devtools extension. Download and
unpack the .zip file, use `chrome://extensions` in Developer Mode and load the
unpacked extension. Then open or reopen devtools. The Preprocessor panel has a
**reload** button that triggers a simple preprocessor.
The preprocessor runs in an isolated world similar to the environment of Chrome
content scripts. A `window` object is available but it shares no properties with
the Web page `window` object. DOM calls in the preprocessor environment will
operate on the Web page, but developers should be cautious about operating on
the DOM in the preprocessor. We do not test such operations though we expect the
result to resemble calls from the outer function of `<script>` tags.
In some applications the developer may coordinate runtime initialization using
the `injectedScript` property in the object passed to the `reload()` call. This
is also JavaScript source code; it is compiled into the page ahead of any Web
page scripts and thus before any JavaScript is preprocessed.
The preprocessor is compiled once just before the first JavaScript appears. It
remains active until the page is reloaded or otherwise navigated. Navigating the
Web page back and then forward will result in no preprocessing. Closing devtools
will leave the preprocessor in place.
## Use Cases
The script preprocessor supports transcoding input source to JavaScript. Use cases include:
* Adding write barriers for Querypoint debugging,
* Supporting feature-specific debugging of next generation EcmaScript using eg Traceur,
* Integration of development tools like coverage analysis.
* Analysis of call sequences for performance tuning.
Several JavaScript compilers support transcoding, including
[Traceur](https://github.com/google/traceur-compiler#readme) and
[Esprima](http://esprima.org/).
## Implementation
The implementation relies on the Devtools front-end hosting an extension
supplying the preprocessor script; the front end communicates with the browser
backend over eg web sockets.
The devtools extension function call issues a postMessage() event from the
devtools extension iframe to the devtools main frame. The event is handled in
`ExtensionServer.js` which forwards it over the
[devtools remote debug protocol](https://developers.google.com/chrome-developer-tools/docs/protocol/1.0/page#command-reload).
(See [Bug 229971](https://crbug.com/229971) for this part of the implementation
and its status).
When the preprocessor script arrives in the back end,
`InspectorPageAgent::reload` stores the preprocessor script in
`m_pendingScriptPreprocessor`. After the browser begins the reload operation, it
calls `PageDebuggerAgent::didClearWindowObjectInWorld` which moves the processor
source into the `scriptDebugServer()`.
Next the browser prepares the page environment and calls
`PageDebuggerAgent::didClearWindowObjectInWorld`. This function clears the
preprocessor object pointer and if it is not recreated during the page load, no
scripts will be preprocessed. At this point we only store the preprocessor
source, delaying the compilation of the preprocessor until just before its first
use. This helps ensure that the JS environment we use is fully initialized.
Source to be preprocessed comes from three different places:
1. Web page `<script>` tags,
1. DOM event-listener attributes, eg `onload`,
1. JS `eval()` or `new Function()` calls.
When the browser encounters either a `<script>` tag
(`ScriptController::executeScriptInMainWorld`) or an element attribute script
(`V8LazyEventListener::prepareListenerObject`) we call a corresponding function
in InspectorInstrumentation. This function has a fast inlined return path in the
case that the debugger is not attached.
If the debugger is attached, InspectorInstrumentation will call the matching
function in PageDebuggerAgent (see core/inspector/InspectorInstrumentation.idl).
It checks to see if the preprocessor is installed. If not, it returns.
The preprocessor source is stored in PageScriptDebugServer.
If the preprocessor is installed, we check to see if it is compiled. If not, we
create a new `ScriptPreprocessor` object. The constructor uses
`ScriptController::executeScriptInIsolatedWorld` to compile the preprocessor in
a new isolated world associated with the Web page's main world. If the
compilation and outer script execution succeed and if the result is a JavaScript
function, we store the resulting function as a `ScopedPersistent<v8::Function>`
member of the preprocessor.
If the `PageScriptDebugServer::preprocess()` has a value for the preprocessor
function, it applies the function to the web page source using
`V8ScriptRunner::callAsFunction()`. This calls the compiled JS function in the
ScriptPreprocessor's isolated world and retrieves the resulting string.
When the preprocessed JavaScript source runs it may call `eval()` or
`new Function()`. These calls cause the V8 runtime to compile source.
Immediately before compiling, V8 issues a beforeCompile event which triggers
`ScriptDebugServer::handleV8DebugEvent()`. This code is only called if the
debugger is active. In the handler we call `ScriptDebugServer::preprocessEval()`
to examine the ScriptCompilationTypeInfo, a marker set by V8, to see if we are
compiling dynamic code. Only dynamic code is preprocessed in this function and
only if we are not executing the preprocessor itself.
During the browser operation, API generation code, debugger console
initialization code, injected page script code, debugger information extraction
code, and regular web page code enter this function. There is currently no way
to distinguish internal or system code from the web page code. However the
internal code is all static. By limiting our preprocessing to dynamic code in
the beforeCompile handler, we know we are only operating on Web page code. The
static Web page code is preprocessed as described above.
## Limitations
We currently do not support preprocessing of WebWorker source code.