summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/resources
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources')
-rw-r--r--chrome/browser/resources/about_memory.html687
-rw-r--r--chrome/browser/resources/about_plugins.html209
-rw-r--r--chrome/browser/resources/about_stats.html316
-rw-r--r--chrome/browser/resources/about_version.html47
-rw-r--r--chrome/browser/resources/browser_resources.vcproj109
-rw-r--r--chrome/browser/resources/debugger_shell.js1246
-rw-r--r--chrome/browser/resources/gear.pngbin0 -> 357 bytes
-rw-r--r--chrome/browser/resources/help.gifbin0 -> 205 bytes
-rw-r--r--chrome/browser/resources/incognito_tab.html31
-rw-r--r--chrome/browser/resources/new_tab.html624
-rw-r--r--chrome/browser/resources/phishing_icon.pngbin0 -> 4645 bytes
-rw-r--r--chrome/browser/resources/safe_browsing_malware_block.html102
-rw-r--r--chrome/browser/resources/safe_browsing_phishing_block.html103
-rw-r--r--chrome/browser/resources/ssl_error.html22
14 files changed, 3496 insertions, 0 deletions
diff --git a/chrome/browser/resources/about_memory.html b/chrome/browser/resources/about_memory.html
new file mode 100644
index 0000000..406a9d0
--- /dev/null
+++ b/chrome/browser/resources/about_memory.html
@@ -0,0 +1,687 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<!--
+about:memory template page
+-->
+<html id="t">
+ <head>
+ <title>About Memory</title>
+
+<style type="text/css">
+body {
+ font-size: 84%;
+ font-family: Arial, Helvetica, sans-serif;
+ padding: 0.75em;
+ margin: 0;
+ min-width: 45em;
+}
+
+h1 {
+ font-size: 110%;
+ font-weight: bold;
+ color: #4a8ee6;
+ letter-spacing: -1px;
+ padding: 0;
+ margin: 0;
+}
+h2 {
+ font-size: 110%;
+ letter-spacing: -1px;
+ font-weight: normal;
+ color: #4a8ee6;
+ padding: 0;
+ margin: 0;
+ padding: 0.5em 1em;
+ color: #3a75bd;
+ margin-left: -38px;
+ padding-left: 38px;
+
+ border-top: 1px solid #3a75bd;
+ padding-top: 0.5em;
+
+}
+h2:first-child {
+ border-top: 0;
+ padding-top: 0;
+}
+span.th {
+ padding-left: 0.35em;
+}
+a {
+ color: black;
+}
+
+div#header {
+ padding: 0.75em 1em;
+ padding-top: 0.6em;
+ padding-left: 0;
+ margin-bottom: 0.75em;
+ position: relative;
+ overflow: hidden;
+ background: #5296de;
+ -webkit-background-size: 100%;
+ border: 1px solid #3a75bd;
+ -webkit-border-radius: 6px;
+ color: white;
+ text-shadow: 0 0 2px black;
+}
+div#header h1 {
+ padding-left: 37px;
+ margin: 0;
+ display: inline;
+ background: url('gear.png') 12px 60% no-repeat;
+ color: white;
+}
+div#header p {
+ font-size: 84%;
+ font-style: italic;
+ padding: 0;
+ margin: 0;
+ color: white;
+ padding-left: 0.4em;
+ display: inline;
+}
+div#header div.navigation {
+ position: absolute;
+ top: 0;
+ right: 1em;
+ line-height: 3.5em;
+ font-size: 92%;
+}
+div#header select {
+ font-size: 100%;
+ font-family: Arial, Helvetica, sans-serif;
+ border: 1px solid #3a75bd;
+ line-height: 140%;
+ color: #315d94;
+}
+div#header select option {
+ padding: 0 0.2em;
+}
+
+div#sidebar {
+ display: none;
+ float: left;
+ margin-left: 26px;
+ width: 45em;
+ min-height: 20em;
+ padding: 0.75em;
+ padding-top: 0;
+
+ border-right: 1px solid #cfcfcf;
+}
+div#content {
+ margin-left: 0px;
+}
+
+div.viewOptions {
+ float: right;
+ font-size: 92%;
+ color: #5f5f5f;
+ margin-top: 1em;
+}
+hr {
+ visibility: hidden;
+ display: inline;
+ padding: 0 0.5em;
+}
+div.viewOptions input {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 100%;
+ border: 1px solid #b5b5b5;
+ -webkit-border-radius: 6px;
+ padding: 0.3em 0.4em;
+}
+div.viewOptions input:focus {
+ border-color: white;
+}
+
+.k {
+ opacity: 0.4;
+ font-weight: normal;
+ padding-left: 0.1em;
+}
+
+.legend {
+ font-size: 84%;
+ padding: 0;
+ padding-top: 0.4em;
+ margin-top: 2em;
+ text-align: right;
+ line-height: 140%;
+ color: #7f7f7f;
+}
+.legend h3 {
+ padding: 0;
+ padding-right: 0.5em;
+ margin: 0;
+ font-weight: normal;
+ color: black;
+ display: inline;
+ font-size: 100%;
+}
+.legend .swatch {
+ opacity: 0.66;
+ padding: 0 0.5em;
+ display: inline-block;
+ margin-right: 0.2em;
+ height: 0.9em;
+}
+.legend .swatch.heavyUse {
+ background: #cc0000;
+}
+
+table.list {
+ width: 100%;
+ line-height: 200%;
+ border-collapse: collapse;
+ font-size: 84%;
+ table-layout: fixed;
+}
+table.list:not([class*='filtered']) tr:nth-child(odd) td {
+ background: #eff3ff;
+}
+.hidden {
+ display: none;
+}
+table.list th {
+ padding: 0 0.5em;
+ vertical-align: top;
+ font-weight: bold;
+ color: #315d94;
+ color: black;
+ white-space: nowrap;
+}
+table.list .firstRow th {
+ text-align: left;
+ line-height: 100%;
+}
+table.list .secondRow * {
+ text-align: left;
+ border-bottom: 1px solid #b5c6de;
+}
+table.list td {
+ padding: 0 0.5em;
+ vertical-align: top;
+ line-height: 1.4em;
+ padding-top: 0.35em;
+}
+table.list tr td:nth-last-child(1),
+table.list tr th:nth-last-child(1) {
+ padding-right: 1em;
+}
+table.list:not([class*='filtered']) .tab .name {
+ padding-left: 1.5em;
+}
+
+table.list .name {
+ width: 100%;
+}
+
+table.list .name div {
+ height: 1.6em;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+table.list .pid {
+ width: 4em;
+ text-align: right;
+}
+table.list .pid .th {
+ padding: 0;
+}
+table.list .type {
+ width: 5em;
+}
+table.list .number {
+ width: 7em;
+ text-align: right;
+}
+table.list .total {
+ font-weight: bold;
+}
+table.list .total .name {
+ color: #315d94;
+ text-align: right;
+}
+table.list .total td {
+ border-top: 1px solid #b5c6de;
+ background: white !important;
+}
+table.list .noResults {
+ display: none;
+}
+table.list.noResults .noResults {
+ display: table-row;
+}
+table.list .noResults td {
+ text-align: center;
+ padding: 3em 0;
+ color: #3f3f3f;
+}
+
+.heavyUse {
+ color: #cc0000;
+ font-weight: bold;
+}
+
+table.list#memoryDetails tr:not([class*='firstRow']) > *:nth-child(2),
+table.list#memoryDetails tr:not([class*='firstRow']) > *:nth-child(5),
+table.list#memoryDetails tr.firstRow th:nth-child(2),
+table.list#memoryDetails tr.firstRow th:nth-child(3) {
+ border-right: 1px solid #b5c6de;
+}
+
+table.list#browserComparison tr:not([class*='firstRow']) > *:nth-child(1),
+table.list#browserComparison tr:not([class*='firstRow']) > *:nth-child(4),
+table.list#browserComparison tr.firstRow th:nth-child(1),
+table.list#browserComparison tr.firstRow th:nth-child(2) {
+ border-right: 1px solid #b5c6de;
+}
+table.list#browserComparison .name {
+ padding-left: 25px;
+ background-position: 5px center;
+ background-repeat: no-repeat;
+}
+
+div.help {
+ display: inline-block;
+ width: 14px;
+ margin: -1px 0;
+ height: 14px;
+ background: url('help.gif') center bottom no-repeat;
+ opacity: 0.33;
+}
+div.help:hover {
+ opacity: 1;
+}
+div.help div {
+ display: none;
+}
+#helpTooltip {
+ z-index: 1000;
+ position: absolute;
+ background: #d6e8ff;
+ padding: 0.3em 0.8em;
+ max-width: 30em;
+ -webkit-box-shadow: 3px 3px 4px rgba(0, 0, 0, 0.33);
+ border: 1px solid #a8cfff;
+ -webkit-border-radius: 0;
+ line-height: 140%;
+ font-size: 92%;
+}
+#helpTooltip p {
+ margin: 0.6em 0;
+}
+div.otherbrowsers {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 84%;
+ width: 100%;
+ text-align: center;
+}
+</style>
+<script>
+function reload() {
+ if (document.getElementById('helpTooltip'))
+ return;
+ history.go(0);
+}
+
+function formatNumber(str) {
+ str += '';
+ var x = str.split('.');
+ var x1 = x[0];
+ var x2 = x.length > 1 ? '.' + x[1] : '';
+ var regex = /(\d+)(\d{3})/;
+ while (regex.test(x1)) {
+ x1 = x1.replace(regex, '$1' + ',' + '$2');
+ }
+ return x1;
+}
+
+function addToSum(id, value) {
+ var target = document.getElementById(id);
+ var sum = parseInt(target.innerHTML);
+ sum += parseInt(value);
+ target.innerHTML = sum;
+}
+
+function handleHelpTooltipMouseOver(event) {
+ var el = document.createElement('div');
+ el.id = 'helpTooltip';
+ el.innerHTML = event.toElement.getElementsByTagName('div')[0].innerHTML;
+ el.style.top = 0;
+ el.style.left = 0;
+ el.style.visibility = 'hidden';
+ document.body.appendChild(el);
+
+ var width = el.offsetWidth;
+ var height = el.offsetHeight;
+
+ if (event.pageX - width - 50 + document.body.scrollLeft >= 0 ) {
+ el.style.left = (event.pageX - width - 20) + 'px';
+ } else {
+ el.style.left = (event.pageX + 20) + 'px';
+ }
+
+
+ if (event.pageY - height - 50 + document.body.scrollTop >= 0) {
+ el.style.top = (event.pageY - height - 20) + 'px';
+ } else {
+ el.style.top = (event.pageY + 20) + 'px';
+ }
+
+ el.style.visibility = 'visible';
+}
+
+function handleHelpTooltipMouseOut(event) {
+ var el = document.getElementById('helpTooltip');
+ el.parentNode.removeChild(el);
+}
+
+function enableHelpTooltips() {
+ var helpEls = document.getElementsByClassName('help');
+
+ for (var i = 0, helpEl; helpEl = helpEls[i]; i++) {
+ helpEl.onmouseover = handleHelpTooltipMouseOver;
+ helpEl.onmouseout = handleHelpTooltipMouseOut;
+ }
+}
+
+//setInterval("reload()", 10000);
+</script>
+</head>
+<body>
+ <div id='header'>
+ <h1>
+ About memory
+ </h1>
+ <p>
+ Measuring memory usage in a multi-process browser
+ </p>
+ </div>
+
+ <div id='content'>
+ <h2>
+ Summary
+ <div class='help'>
+ <div>
+ <p>
+ Summary of memory used by currently active browsers.
+ For browsers which use multiple processes, memory reflects
+ aggregate memory used across all browser processes.<p>
+ For chrome, processes used to to display diagnostics
+ information (such as this "about:memory") are excluded.
+ </p>
+ </div>
+ </div>
+ </h2>
+
+ <table class='list' id='browserComparison'>
+ <colgroup>
+ <col class='name' />
+ <col class='number' />
+ <col class='number' />
+ <col class='number' />
+ <col class='number' />
+ <col class='number' />
+ </colgroup>
+ <tr class='firstRow doNotFilter'>
+ <th>
+ </th>
+ <th colspan='3'>
+ Memory
+ <div class='help'>
+ <div>
+ <p>
+ <strong>Memory</strong>
+ </p>
+ <p>
+ <strong>Private:</strong>
+ Resident memory size that is not shared with any other process.
+ This is the best indicator of browser memory resource usage.
+ </p>
+ <p>
+ <strong>Shared:</strong>
+ Resident memory size that is currently shared with 2 or more processes.
+ Note: For browsers using multiple processes, if we simply added the shared memory
+ of each individual process, this value would be inflated. Therefore, this value
+ is computed as an approximate value for shared memory in each of the browser's
+ processes. Note also that shared memory varies depending on what other processes
+ are running on the system, and may be difficult to measure reproducibly.
+ </p>
+ <p>
+ <strong>Total:</strong>
+ The sum of the private + shared resident memory sizes.
+ </p>
+ </div>
+ </div>
+ </th>
+ <th colspan='2'>
+ Virtual memory
+ <div class='help'>
+ <div>
+ <p>
+ <strong>Virtual memory</strong>
+ </p>
+ <p>
+ <strong>Private:</strong>
+ The resident and paged bytes committed for use by only this process.
+ </p>
+ <p>
+ <strong>Mapped:</strong>
+ Total bytes allocated by this process that are mapped into the
+ view of a section, backed by either system pagefile or file system. This
+ is primarily memory-mapped files.
+ </p>
+ </div>
+ </div>
+ </th>
+ </tr>
+ <tr class='secondRow doNotFilter'>
+ <th class='name'>
+ Browser
+ </th>
+ <th class='name'>
+ Private
+ </th>
+ </th>
+ <th class='number'>
+ Shared
+ </th>
+ <th class='number'>
+ Total
+ </th>
+ <th class='number'>
+ Private
+ </th>
+ <th class='number'>
+ Mapped
+ </th>
+ </tr>
+ <tr jsselect="browsers">
+ <td class='name'>
+ <div>
+ <strong jscontent="name"></strong> <span jscontent="version"></span>
+ </div>
+ </td>
+ <td class='number'>
+ <span class='th' jscontent="formatNumber(ws_priv + ws_shareable - ws_shared)"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jscontent="formatNumber(ws_shared / processes)"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jscontent="formatNumber(ws_priv + ws_shareable - ws_shared + (ws_shared / processes))"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jscontent="formatNumber(comm_priv)"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jscontent="formatNumber(comm_map)"></span><span class='k'>k</span>
+ </td>
+ </tr>
+ </table>
+ <div class=otherbrowsers jsdisplay="browsers.length == 1">
+ Note: If other browsers (IE, Firefox, Opera, Safari) are running,
+ I'll show their memory details here.
+ </div>
+
+ <br /><br /><br />
+
+ <h2>
+ Processes
+ <div class='help'>
+ <div>
+ <p>
+ Details of memory usage for each of Chrome's processes.
+ </p>
+ </div>
+ </div>
+ </h2>
+
+ <table class='list' id='memoryDetails'>
+ <colgroup>
+ <col class='pid' />
+ <col class='name' />
+ <col class='number' />
+ <col class='number' />
+ <col class='number' />
+ <col class='number' />
+ <col class='number' />
+ </colgroup>
+ <tr class='firstRow doNotFilter'>
+ <th>
+ </th>
+ <th>
+ </th>
+ <th colspan='3'>
+ Memory
+ </th>
+ <th colspan='2'>
+ Virtual memory
+ </th>
+
+ </tr>
+ <tr class='secondRow doNotFilter'>
+ <th class='pid'>
+ PID
+ </th>
+ <th class='name'>
+ Name
+ </th>
+ <th class='number'>
+ Private
+ </th>
+ <th class='number'>
+ Shared
+ </th>
+ <th class='number'>
+ Total
+ </th>
+ <th class='number'>
+ Private
+ </th>
+ <th class='number'>
+ Mapped
+ </th>
+ </tr>
+
+ <tr jsselect="browzr_data">
+ <td class='pid'>
+ <span class='th' jscontent="pid"></span>
+ </td>
+ <td class='name'>
+ <div>
+ Browser
+ </div>
+ </td>
+ <td class='number'>
+ <span class='th' jseval="addToSum('tot_ws_priv', $this.ws_priv + $this.ws_shareable - $this.ws_shared)" jscontent="ws_priv + ws_shareable - ws_shared"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jscontent="ws_shared"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jseval="addToSum('tot_ws_tot', $this.ws_priv + $this.ws_shareable)" jscontent="ws_priv + ws_shareable"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jseval="addToSum('tot_comm_priv', $this.comm_priv)" jscontent="comm_priv"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jseval="addToSum('tot_comm_map', $this.comm_map)" jscontent="comm_map"></span><span class='k'>k</span>
+ </td>
+ </tr>
+ <tr jsselect="renderer_data">
+ <td class='pid'>
+ <span class='th' jscontent="pid"></span>
+ </td>
+ <td class='name'>
+ <div jscontent="renderer_id"></div>
+ <div jsselect="titles">
+ <span jscontent="$this"></span><br>
+ </div>
+ </td>
+ <td class='number'>
+ <span class='th' jseval="addToSum('tot_ws_priv', $this.ws_priv + $this.ws_shareable - $this.ws_shared)" jscontent="ws_priv + ws_shareable - ws_shared"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jscontent="ws_shared"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jseval="addToSum('tot_ws_tot', $this.ws_priv + $this.ws_shareable)" jscontent="ws_priv + ws_shareable"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jseval="addToSum('tot_comm_priv', $this.comm_priv)" jscontent="comm_priv"></span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' jseval="addToSum('tot_comm_map', $this.comm_map)" jscontent="comm_map"></span><span class='k'>k</span>
+ </td>
+ </tr>
+ <tr class='total doNotFilter'>
+ <td class='pid'>
+ </td>
+ <td class='name'>
+ &Sigma;
+ </td>
+ <td class='number'>
+ <span class='th' id="tot_ws_priv">0</span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ </td>
+ <td class='number'>
+ <span class='th' id="tot_ws_tot">0</span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <span class='th' id="tot_comm_priv">0</span><span class='k'>k</span>
+ </td>
+ <td class='number'>
+ <div class='help'>
+ <div>
+ <p>
+ This is an approximation. Conceptually, this is the total
+ amount of in-memory pages for the entire logical Chrome
+ application, without double counting shared pages (e.g.
+ mapped
+ DLLs, SharedMemory bitmaps, etc.) across the browser and
+ renderers.
+ </p>
+ </div>
+ </div>
+ <span class='th' id="tot_comm_map">0</span><span class='k'>k</span>
+ </td>
+ </tr>
+
+ <tr class='noResults'>
+ <td colspan='99'>
+ No results found.
+ </td>
+ </tr>
+ </table>
+ </div>
+</body>
+<script>
+ enableHelpTooltips();
+</script>
+</html>
diff --git a/chrome/browser/resources/about_plugins.html b/chrome/browser/resources/about_plugins.html
new file mode 100644
index 0000000..eb0cad7
--- /dev/null
+++ b/chrome/browser/resources/about_plugins.html
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<!--
+A modified version of the about:plugins page found in Mozilla. The license of
+the original file is below.
+-->
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is mozilla.org Code.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Mark Olson <maolson@earthlink.net>
+ - Alexey Chernyak <alexeyc@bigfoot.com>
+ - Frank Tang <ftang@netscape.com>
+ - Mike Connelly <mozilla@shepherdstown.com>
+ - Robert Kaiser <kairo@kairo.at>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<html id="t">
+<head>
+<title jscontent="title"></title>
+<style>
+body {
+ background-color: Window;
+ color: WindowText;
+ font: message-box;
+}
+
+div#outside {
+ text-align: justify;
+ width: 90%;
+ margin-left: 5%;
+ margin-right: 5%;
+}
+
+div#plugs {
+ text-align: center;
+ font-size: xx-large;
+ font-weight: bold;
+}
+
+div#noplugs {
+ font-size: x-large;
+ font-weight: bold;
+}
+
+div.plugname {
+ margin-top: 2em;
+ margin-bottom: 1em;
+ font-size: large;
+ text-align: left;
+ font-weight: bold;
+}
+
+dl {
+ margin: 0px 0px 3px 0px;
+}
+
+table {
+ background-color: Window;
+ color: WindowText;
+ font: message-box;
+ text-align: left;
+ width: 100%;
+ border: 1px solid ThreeDShadow;
+ border-spacing: 0px;
+}
+
+th {
+ text-align: center;
+ background-color: Highlight;
+ color: HighlightText;
+}
+
+th + th,
+td + td {
+ border-left: 1px dotted ThreeDShadow;
+}
+
+td {
+ text-align: left;
+ border-top: 1px dotted ThreeDShadow;
+}
+
+th, td {
+ padding: 3px;
+}
+
+th.type, th.suff {
+ width: 20%;
+}
+
+th.desc {
+ width: 50%;
+}
+
+th.enabled {
+ width: 10%;
+}
+</style>
+</head>
+<body>
+<div id="outside">
+<script type="application/x-javascript">
+
+ /* JavaScript to enumerate and display all installed plug-ins
+
+ * First, refresh plugins in case anything has been changed recently in
+ * prefs: (The "false" argument tells refresh not to reload or activate
+ * any plug-ins that would be active otherwise. In contrast, one would
+ * use "true" in the case of ASD instead of restarting)
+ */
+
+ navigator.plugins.refresh(false);
+
+ var numPlugins = navigator.plugins.length;
+
+ if (numPlugins > 0)
+ document.writeln('<div id="plugs" jscontent="headingPlugs"><\/div>');
+ else
+ document.writeln('<div id="noplugs" jscontent="headingNoPlugs"><\/div>');
+
+ for (var i = 0; i < numPlugins; i++)
+ {
+ var plugin = navigator.plugins[i];
+
+ if (plugin)
+ {
+ document.write("<div class=\"plugname\">");
+ document.write(plugin.name);
+ document.writeln("<\/div>");
+
+ document.writeln('<dl><dd><span jscontent="filename"><\/span> ');
+ document.write(plugin.filename);
+ document.writeln("<\/dd><dd>");
+ document.write(plugin.description);
+ document.writeln("<\/dd><\/dl>");
+
+ document.writeln('<table class="contenttable">');
+ document.writeln("<thead>");
+ document.writeln('<tr><th class="type" jscontent="mimetype"><\/th>');
+ document.writeln('<th class="desc" jscontent="description"><\/th>');
+ document.writeln('<th class="suff" jscontent="suffixes"><\/th>');
+ document.writeln('<th class="enabled" jscontent="enabled"><\/th><\/tr>');
+ document.writeln("<\/thead>");
+ document.writeln("<tbody>");
+
+ var numTypes = plugin.length;
+ var mimetype;
+ var enabled;
+ var enabledPlugin;
+ for (var j = 0; j < numTypes; j++)
+ {
+ mimetype = plugin[j];
+
+ if (mimetype)
+ {
+ enabled = "enabled_no";
+ enabledPlugin = mimetype.enabledPlugin;
+ if (enabledPlugin && (enabledPlugin.filename == plugin.filename))
+ enabled = "enabled_yes";
+
+ document.writeln("<tr>");
+ document.writeln("<td>" + mimetype.type + "<\/td>");
+ document.writeln("<td>" + mimetype.description + "<\/td>");
+ document.writeln("<td>" + mimetype.suffixes + "<\/td>");
+ document.writeln('<td jscontent="' + enabled + '"><\/td>');
+ document.writeln("<\/tr>");
+ }
+ }
+
+ document.write("<\/tbody>");
+ document.write("<\/table>");
+ }
+ }
+</script>
+</div>
+</body>
+</html>
diff --git a/chrome/browser/resources/about_stats.html b/chrome/browser/resources/about_stats.html
new file mode 100644
index 0000000..8354fe5
--- /dev/null
+++ b/chrome/browser/resources/about_stats.html
@@ -0,0 +1,316 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<html id="t">
+ <head>
+ <title>About Stats</title>
+
+<style type="text/css">
+body {
+ border-top: 10px solid #3B85E3;
+ color: #333;
+ font-family: Verdana,Arial,Helvetica,sans-serif;
+}
+body, td {
+ font-size: 11px;
+}
+a:link, a:visited {
+ color: #2C3EBA;
+ text-decoration: none;
+}
+a:hover {
+ color: red;
+ text-decoration: underline;
+}
+h1 {
+ border-left: 10px solid #FFF;
+ font-size: 16px;
+ font-weight: bold;
+ margin: 0;
+ padding: 0.2em;
+ color: #3B85E3;
+}
+h2 {
+ border-left: 10px solid #FFF;
+ font-size: 11px;
+ font-weight: normal;
+ margin: 0;
+ padding: 0 6em 0.2em 0.2em;
+}
+.details {
+ margin: 0.4em 1.9em 0 1.2em;
+ padding: 0 0.4em 0.3em 0;
+ white-space: nowrap;
+}
+.details .outer {
+ padding-right: 0;
+ vertical-align: top;
+}
+.details .top {
+ border-top: 2px solid #333;
+ font-weight: bold;
+ margin-top: 0.4em;
+}
+.details .header2 {
+ font-weight: bold;
+ padding-left: 0.9em;
+}
+.details .key {
+ padding-left: 1.1em;
+ vertical-align: top;
+}
+.details .value {
+ text-align: right;
+ color: #333;
+ font-weight: bold;
+}
+.details .zebra {
+ background: #EEE;
+}
+.lower {
+ text-transform: lowercase;
+}
+</style>
+<script>
+
+/* Counter accessor for Name Node. */
+function getCounterNameFromCounterNode(node) {
+ return node.childNodes[1];
+}
+
+/* Counter accessor for Value Node. */
+function getCounterValueFromCounterNode(node) {
+ return node.childNodes[3];
+}
+
+/* Counter accessor for Delta Node. */
+function getCounterDeltaFromCounterNode(node) {
+ return node.childNodes[5];
+}
+
+/* Timer accessor for Name Node. */
+function getTimerNameFromTimerNode(node) {
+ return node.childNodes[1];
+}
+
+/* Timer accessor for Value Node. */
+function getTimerValueFromTimerNode(node) {
+ return node.childNodes[3];
+}
+
+/* Timer accessor for Time Node. */
+function getTimerTimeFromTimerNode(node) {
+ return node.childNodes[5];
+}
+
+/* Timer accessor for Average Time Node. */
+function getTimerAvgTimeFromTimerNode(node) {
+ return node.childNodes[7];
+}
+
+/* Do the filter work. Hide all nodes matching node.*/
+function filterMatching(text, nodelist, functionToGetNameNode) {
+ var showAll = text.length == 0;
+ for (var i = 0, node; node = nodelist[i]; i++) {
+ var name = functionToGetNameNode(node).innerHTML.toLowerCase();
+ if (showAll || name.indexOf(text) >= 0) {
+ node.style.display = "table-row";
+ } else {
+ node.style.display = "none";
+ }
+ }
+}
+
+/* Hides or shows counters based on the user's current filter selection. */
+function doFilter() {
+ var filter = document.getElementById("filter");
+ var text = filter.value.toLowerCase();
+ var nodes = document.getElementsByName("counter");
+ filterMatching(text, nodes, getCounterNameFromCounterNode);
+ var nodes = document.getElementsByName("timer");
+ filterMatching(text, nodes, getTimerNameFromTimerNode);
+}
+
+/* Colors the counters based on increasing or decreasing value. */
+function doColor() {
+ var nodes = document.getElementsByName("counter");
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var child = getCounterDeltaFromCounterNode(node);
+ var delta = child.innerHTML;
+ if (delta > 0) {
+ child.style.color = "Green";
+ } else if (delta == 0) {
+ child.style.color = "Black";
+ } else {
+ child.style.color = "Red";
+ }
+ }
+}
+
+/* Counters with no values are null. Remove them. */
+function removeNullValues() {
+ var nodes = document.getElementsByName("counter");
+ for (var i = nodes.length - 1; i >= 0; i--) {
+ var node = nodes[i];
+ var value = getCounterValueFromCounterNode(node).innerHTML;
+ if (value == "null") {
+ node.parentNode.removeChild(node);
+ }
+ }
+ var nodes = document.getElementsByName("timer");
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var value_node = getTimerValueFromTimerNode(node);
+ if (value_node.innerHTML == "null") {
+ value_node.innerHTML = "";
+ }
+ }
+}
+
+/* Compute the average time for timers */
+function computeTimes() {
+ var nodes = document.getElementsByName("timer");
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var count = getTimerValueFromTimerNode(node).innerHTML;
+ if (count.length > 0) {
+ var time = getTimerTimeFromTimerNode(node).innerHTML;
+ var avg = getTimerAvgTimeFromTimerNode(node);
+ avg.innerHTML = Math.round(time / count * 100) / 100;
+ }
+ }
+}
+
+/* All the work we do onload. */
+function onLoadWork() {
+ doColor();
+ removeNullValues();
+ computeTimes();
+ document.getElementById("filter").focus();
+}
+
+// The function should only be used as the event handler
+// on a table cell element. To use it, put it in a <td> element:
+// <td onclick="sort('string')" ...>
+//
+// The function sorts rows after the row with onclick event handler.
+//
+// type: the data type, 'string', 'number'
+function sort_table(type){
+ var cell = event.target;
+ var cnum = cell.cellIndex;
+
+ var row = cell.parentNode;
+ var start_index = row.rowIndex + 1;
+
+ var tbody = row.parentNode;
+ var table = tbody.parentNode;
+
+ var rows = new Array();
+
+ var indexes = new Array();
+ // skip the first row
+ for (var i = start_index; i < table.rows.length; i++)
+ rows.push(table.rows[i]);
+
+ // a, b are strings
+ function compare_strings(a,b) {
+ if (a == b) return 0;
+ if (a < b) return -1;
+ return 1;
+ }
+
+ // a, b are numbers
+ function compare_numbers(a,b) {
+ var x = isNaN(a) ? 0 : a;
+ var y = isNaN(b) ? 0 : b;
+ return x - y;
+ }
+
+ var sort_func = undefined;
+ if (type === 'string') {
+ sort_func = function(a, b) {
+ var x = a.cells[cnum].innerText;
+ var y = b.cells[cnum].innerText;
+ return compare_strings(x, y);
+ } ;
+
+ } else if (type === 'number') {
+ sort_func = function(a, b) {
+ var x = parseFloat(a.cells[cnum].innerText);
+ var y = parseFloat(b.cells[cnum].innerText);
+ return compare_numbers(x, y);
+ }
+ }
+
+ rows.sort(sort_func);
+
+ // change tables
+ if (cell._reverse) {
+ for (var i = rows.length - 1; i >= 0; i--)
+ tbody.appendChild(rows[i]);
+ cell._reverse = false;
+ } else {
+ for (var i = 0; i < rows.length; i++)
+ tbody.appendChild(rows[i]);
+ cell._reverse = true;
+ }
+}
+
+</script>
+</head>
+<body onload="onLoadWork()">
+ <div style="float: right">
+ <br>Filter: <input id="filter" type="text" value="" onkeyup="doFilter()">
+ </div>
+ <h1 class="lower">About Stats</h1>
+ <h2>Shhh! This page is secret!</h2><br/>
+ <table class="details" cellspacing="0" cellpadding="0" border="0">
+ <tbody>
+ <tr>
+ <td class="outer">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tbody>
+ <tr>
+ <td class="top" width="100">Counters</td>
+ <td class="top value" colspan=2></td>
+ </tr>
+ <tr>
+ <td class="header2 lower" width="200" onclick="sort_table('string')">name</td>
+ <td class="header2 lower" onclick="sort_table('number')">value</td>
+ <td class="header2 lower" onclick="sort_table('number')">delta</td>
+ </tr>
+ <tr jsselect="counters" name="counter">
+ <td class="key" width="200" jscontent="name"></td>
+ <td class="value" jscontent="value"></td>
+ <td class="value" jscontent="delta"></td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td width="15"/>
+ <td class="outer">
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tbody>
+ <tr>
+ <td class="top" width="100">Timers</td>
+ <td class="top value"></td>
+ <td class="top value" colspan=3></td>
+ </tr>
+ <tr>
+ <td class="header2 lower" width="200" onclick="sort_table('string')">name</td>
+ <td class="header2 lower" onclick="sort_table('number')">count</td>
+ <td class="header2 lower" onclick="sort_table('number')">time (ms)</td>
+ <td class="header2 lower" onclick="sort_table('number')">avg time (ms)</td>
+ </tr>
+ <tr jsselect="timers" name="timer">
+ <td class="key" width="200" jscontent="name"></td>
+ <td class="value" jscontent="value"></td>
+ <td class="value" jscontent="time"></td>
+ <td class="value"></td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+ </table><br/>
+</body>
+</html>
diff --git a/chrome/browser/resources/about_version.html b/chrome/browser/resources/about_version.html
new file mode 100644
index 0000000..b56b3dd
--- /dev/null
+++ b/chrome/browser/resources/about_version.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<!--
+about:version template page
+-->
+
+<html id="t">
+<head>
+<title jscontent="title"></title>
+<style type="text/css">
+body {
+ background-color: Window;
+ color: WindowText;
+ font: message-box;
+}
+#outer {
+ text-align: left;
+}
+#name {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+#logo {
+ float: left;
+ padding-right: 20px;
+ padding-bottom: 200px;
+}
+#useragent {
+ white-space: nowrap;
+ font-face: fixed;
+ font-size: 0.8em;
+}
+</style>
+</head>
+<body>
+<!-- TODO: figure out a way to embed a real image -->
+<img id="logo" src="http://www.google.com/intl/en_ALL/images/logo.gif" />
+<div id="outer">
+<div id="name" jscontent="name"></div>
+<div id="version"><span jscontent="version"></span> (<span jscontent="cl"></span>)</div>
+<div id="official" jscontent="official"></div>
+<div id="company" jscontent="company"></div>
+<div id="copyright" jscontent="copyright"></div>
+<div id="useragent" jscontent="useragent"></div>
+</div>
+</body>
+</html>
diff --git a/chrome/browser/resources/browser_resources.vcproj b/chrome/browser/resources/browser_resources.vcproj
new file mode 100644
index 0000000..a0a0b69
--- /dev/null
+++ b/chrome/browser/resources/browser_resources.vcproj
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="browser_resources"
+ ProjectGUID="{B95AB527-F7DB-41E9-AD91-EB51EE0F56BE}"
+ RootNamespace="browser_resources"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ <ToolFile
+ RelativePath="..\..\tools\build\win\flattened_html_file.rules"
+ />
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="10"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="Flattened HTML Resource"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="10"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="Flattened HTML Resource"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\about_memory.html"
+ >
+ </File>
+ <File
+ RelativePath=".\about_stats.html"
+ >
+ </File>
+ <File
+ RelativePath=".\new_tab.html"
+ >
+ </File>
+ <File
+ RelativePath=".\incognito_tab.html"
+ >
+ </File>
+ <File
+ RelativePath=".\safe_browsing_malware_block.html"
+ >
+ </File>
+ <File
+ RelativePath=".\safe_browsing_phishing_block.html"
+ >
+ </File>
+ <File
+ RelativePath="..\security\resources\ssl_error.html"
+ >
+ </File>
+ <File
+ RelativePath="..\security\resources\ssl_roadblock.html"
+ >
+ </File>
+ <File
+ RelativePath="..\security\resources\ssl_roadblock_background.png"
+ >
+ </File>
+ <File
+ RelativePath="..\security\resources\ssl_roadblock_icon.png"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/browser/resources/debugger_shell.js b/chrome/browser/resources/debugger_shell.js
new file mode 100644
index 0000000..4685896
--- /dev/null
+++ b/chrome/browser/resources/debugger_shell.js
@@ -0,0 +1,1246 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+
+// TODO(erikkay): look into how this can be split up into multiple files
+// It's currently loaded explicitly by Chrome, so maybe I need an "include"
+// or "source" builtin to allow a core source file to reference multiple
+// sub-files.
+
+/**
+ * @fileoverview Shell objects and global helper functions for Chrome
+ * automation shell / debugger. This file is loaded into the global namespace
+ * of the interactive shell, so users can simply call global functions
+ * directly.
+ * @author erikkay@google.com (Erik Kay)
+ */
+
+/**
+ * Sequence number of the DebugCommand.
+ */
+DebugCommand.next_seq_ = 0;
+
+/**
+ * Command messages to be sent to the debugger.
+ * @constructor
+ */
+function DebugCommand(str) {
+ this.command = undefined;
+ // first, strip off of the leading word as the command
+ var argv = str.split(' ');
+ this.user_command = argv.shift();
+ // the rest of the string is argv to the command
+ str = argv.join(' ');
+ if (DebugCommand.aliases[this.user_command])
+ this.user_command = DebugCommand.aliases[this.user_command];
+ if (this.parseArgs_(str) == 1)
+ this.type = "request";
+ if (this.command == undefined)
+ this.command = this.user_command;
+};
+
+// Mapping of some control characters to avoid the \uXXXX syntax for most
+// commonly used control cahracters.
+const ctrlCharMap_ = {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+};
+
+// Regular expression matching ", \ and control characters (0x00 - 0x1F)
+// globally.
+const ctrlCharMatch_ = /["\\\\\x00-\x1F]/g;
+
+/**
+ * Convert a String to its JSON representation.
+ * @param {String} value - String to be converted
+ * @return {String} JSON formatted String
+ */
+DebugCommand.stringToJSON = function(value) {
+ // Check for" , \ and control characters (0x00 - 0x1F).
+ if (ctrlCharMatch_.test(value)) {
+ // Replace ", \ and control characters (0x00 - 0x1F).
+ return '"' + value.replace(ctrlCharMatch_, function (char) {
+ // Use charmap if possible.
+ var mapped = ctrlCharMap_[char];
+ if (mapped) return mapped;
+ mapped = char.charCodeAt();
+ // Convert control character to unicode escape sequence.
+ var dig1 = (Math.floor(mapped / 16));
+ var dig2 = (mapped % 16)
+ return '\\u00' + dig1.toString(16) + dig2.toString(16);
+ })
+ + '"';
+ }
+
+ // Simple string with no special characters.
+ return '"' + value + '"';
+};
+
+/**
+ * @return {bool} True if x is an integer.
+ */
+DebugCommand.isInt = function(x) {
+ var y = parseInt(x);
+ if (isNaN(y))
+ return false;
+ return x == y && x.toString() == y.toString();
+};
+
+/**
+ * @return {float} log base 10 of num
+ */
+DebugCommand.log10 = function(num) {
+ return Math.log(num)/Math.log(10);
+};
+
+/**
+ * Take an object and encode it (non-recursively) as a JSON dict.
+ * @param {Object} obj - object to encode
+ */
+DebugCommand.toJSON = function(obj) {
+ var json = '{';
+ for (var key in obj) {
+ var val = obj[key];
+ if (!DebugCommand.isInt(val)) {
+ val = DebugCommand.stringToJSON(val.toString());
+ }
+ json += '"' + key + '":' + val + ',';
+ }
+ json += '}';
+ return json;
+};
+
+/**
+ * Encode the DebugCommand object into the V8 debugger JSON protocol format.
+ * @see http://wiki/Main/V8Debugger
+ */
+DebugCommand.prototype.toJSONProtocol = function() {
+ var json = '{';
+ json += '"seq":"' + this.seq;
+ json += '","type":"' + this.type;
+ json += '","command":"' + this.command + '"';
+ if (this.arguments) {
+ json += ',"arguments":' + DebugCommand.toJSON(this.arguments);
+ }
+ json += '}'
+ return json;
+}
+
+/**
+ * Encode the contents of this message and send it to the debugger.
+ * @param {Object} tab - tab being debugged. This is an internal
+ * Chrome object.
+ */
+DebugCommand.prototype.sendToDebugger = function(tab) {
+ this.seq = DebugCommand.next_seq_++;
+ str = this.toJSONProtocol();
+ dprint("sending: " + str);
+ tab.sendToDebugger(str);
+};
+
+DebugCommand.trim = function(str) {
+ return str.replace(/^\s*/, '').replace(/\s*$/, '');
+};
+
+/**
+ * Strip off a trailing parameter after a ':'. As the identifier for the
+ * source can contain ':' characters (e.g. 'http://www....) something after
+ * a ':' is only considered a parameter if it is numeric.
+ * @return {Array} two element array, the trimmed string and the parameter,
+ * or -1 if no parameter
+ */
+DebugCommand.stripTrailingParameter = function(str, opt_separator) {
+ var sep = opt_separator || ':';
+ var index = str.lastIndexOf(sep);
+ // If a separator character if found strip if numeric.
+ if (index != -1) {
+ var value = parseInt(str.substring(index + 1, str.length), 10);
+ if (isNaN(value) || value < 0) {
+ return [str, -1];
+ }
+ str = str.substring(0, index);
+ return [str, value];
+ }
+ return [str, -1];
+};
+
+/**
+ * Format source and location strings based on source location input data.
+ * @param {Object} script - script information object
+ * @param {String} source - source code for the current location
+ * @param {int} line - line number (0-based)
+ * @param {String} func - function name
+ * @return {array} [location(string), source line(string), line number(int)]
+ */
+DebugCommand.getSourceLocation = function(script, source, line, func) {
+ // source line is 0-based, we present as 1-based
+ line++;
+
+ // TODO(erikkay): take column into account as well
+ if (source)
+ source = "" + line + ": " + source;
+ var location;
+ if (func) {
+ location = func + ", ";
+ }
+ location += script ? script.name : '[no source]';
+ return [location, source, line];
+};
+
+/**
+ * Aliases for debugger commands.
+ */
+DebugCommand.aliases = {
+ 'b': 'break',
+ 'bi': 'break_info',
+ 'br': 'break',
+ 'bt': 'backtrace',
+ 'c': 'continue',
+ 'f': 'frame',
+ 'h': 'help',
+ '?': 'help',
+ 'ls': 'source',
+ 'n': 'next',
+ 'p': 'print',
+ 's': 'step',
+ 'so': 'stepout',
+};
+
+/**
+ * Parses arguments to simple commands which have no arguments.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.parseSimpleCommand_ = function(str) {
+ return str.length ? -1 : 1;
+};
+
+/**
+ * Parses arguments to "args" and "locals" command, and initializes
+ * the underlying DebugCommand (which is a frame request).
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseArgsAndLocals_ = function(str) {
+ this.command = "frame";
+ return str.length ? -1 : 1;
+};
+
+/**
+ * Parses arguments to "break_info" command, and executes it.
+ * "break_info" has an optional argument, which is the breakpoint
+ * identifier.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 0 for success
+ */
+DebugCommand.prototype.parseBreakInfo_ = function(str) {
+ this.type = "shell";
+
+ // Array of breakpoints to be printed by this command
+ // (default to all breakpoints)
+ var breakpointsToPrint = shell_.breakpoints;
+
+ if (str.length > 0) {
+ // User specified an invalid breakpoint (not a number)
+ if (!str.match(/^\s*\d+\s*$/))
+ return -1; // invalid usage
+
+ // Check that the specified breakpoint identifier exists
+ var id = parseInt(str);
+ var info = shell_.breakpoints[id];
+ if (!info) {
+ print("Error: Invalid breakpoint");
+ return 0; // success (of sorts)
+ }
+ breakpointsToPrint = [info];
+ } else {
+ // breakpointsToPrint.length isn't accurate, because of
+ // deletions
+ var num_breakpoints = 0;
+ for (var i in breakpointsToPrint) num_breakpoints++;
+
+ print("Num breakpoints: " + num_breakpoints);
+ }
+
+ DebugShell.printBreakpoints_(breakpointsToPrint);
+
+ return 0; // success
+}
+
+/**
+ * Parses arguments to "step" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseStep_ = function(str, opt_stepaction) {
+ this.command = "continue";
+ action = opt_stepaction || "in";
+ this.arguments = {"stepaction" : action}
+ if (str.length) {
+ count = parseInt(str);
+ if (count > 0) {
+ this.arguments["stepcount"] = count;
+ } else {
+ return -1;
+ }
+ }
+ return 1;
+};
+
+/**
+ * Parses arguments to "step" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseStepOut_ = function(str) {
+ return this.parseStep_(str, "out");
+};
+
+/**
+ * Parses arguments to "next" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseNext_ = function(str) {
+ return this.parseStep_(str, "next");
+};
+
+/**
+ * Parse the arguments to "print" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return 1 - always succeeds
+ */
+DebugCommand.prototype.parsePrint_ = function(str) {
+ this.command = "evaluate";
+ this.arguments = { "expression" : str };
+ // If the page is in the running state, then we force the expression to
+ // evaluate in the global context to avoid evaluating in a random context.
+ if (shell_.running)
+ this.arguments["global"] = true;
+ return 1;
+};
+
+/**
+ * Handle the response to a "print" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object
+ */
+DebugCommand.responsePrint_ = function(msg) {
+ body = msg["body"];
+ if (body['text'] != undefined) {
+ print(body['text']);
+ } else {
+ // TODO(erikkay): is "text" ever not set?
+ print("can't print response");
+ }
+};
+
+/**
+ * Parses arguments to "break" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success, 0 for handled internally
+ */
+DebugCommand.prototype.parseBreak_ = function(str) {
+ function stripTrailingParameter() {
+ var ret = DebugCommand.stripTrailingParameter(str, ':');
+ str = ret[0];
+ return ret[1];
+ }
+
+ if (str.length == 0) {
+ this.type = "shell";
+ return 0;
+ } else {
+ var parts = str.split(/\s+/);
+ var condition = null;
+ if (parts.length > 1) {
+ str = parts.shift();
+ condition = parts.join(" ");
+ }
+
+ this.command = "setbreakpoint";
+
+ // Locate ...[:line[:column]] if present.
+ var line = -1;
+ var column = -1;
+ line = stripTrailingParameter();
+ if (line != -1) {
+ line -= 1;
+ var l = stripTrailingParameter();
+ if (l != -1) {
+ column = line;
+ line = l - 1;
+ }
+ }
+
+ if (line == -1 && column == -1) {
+ this.arguments = { 'type' : 'function',
+ 'target' : str };
+ } else {
+ var script = shell_.matchScript(str, line);
+ if (script) {
+ this.arguments = { 'type' : 'script',
+ 'target' : script.name };
+ } else {
+ this.arguments = { 'type' : 'function',
+ 'target' : str };
+ }
+ this.arguments.line = line;
+ if (column != -1)
+ this.arguments.position = column;
+ }
+ if (condition)
+ this.arguments.condition = condition;
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "break" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object
+ */
+DebugCommand.responseBreak_ = function(msg) {
+ var info = new BreakpointInfo(
+ parseInt(msg.body.breakpoint),
+ msg.command.arguments.type,
+ msg.command.arguments.target,
+ msg.command.arguments.line,
+ msg.command.arguments.position,
+ msg.command.arguments.condition);
+ shell_.addedBreakpoint(info);
+};
+
+/**
+ * Parses arguments to "backtrace" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+ DebugCommand.prototype.parseBacktrace_ = function(str) {
+ if (str.length > 0) {
+ var parts = str.split(/\s+/);
+ var non_empty_parts = parts.filter(function(s) { return s.length > 0; });
+ // We need exactly two arguments.
+ if (non_empty_parts.length != 2) {
+ return -1;
+ }
+ var from = parseInt(non_empty_parts[0], 10);
+ var to = parseInt(non_empty_parts[1], 10);
+ // The two arguments have to be integers.
+ if (from != non_empty_parts[0] || to != non_empty_parts[1]) {
+ return -1;
+ }
+ this.arguments = { 'fromFrame': from, 'toFrame': to + 1 };
+ } else {
+ // Default to fetching the first 10 frames.
+ this.arguments = { 'fromFrame': 0, 'toFrame': 10 };
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "backtrace" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object
+ */
+DebugCommand.responseBacktrace_ = function(msg) {
+ body = msg["body"];
+ if (body && body.totalFrames) {
+ print('Frames #' + body.fromFrame + ' to #' + (body.toFrame - 1) +
+ ' of ' + body.totalFrames + ":");
+ for (var i = 0; i < body.frames.length; i++) {
+ print(body.frames[i].text);
+ }
+ } else {
+ print("unimplemented (sorry)");
+ }
+};
+
+
+/**
+ * Parses arguments to "clear" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseClearCommand_ = function(str) {
+ this.command = "clearbreakpoint";
+ if (str.length > 0) {
+ var i = parseInt(str, 10);
+ if (i != str) {
+ return -1;
+ }
+ this.arguments = { 'breakpoint': i };
+ }
+ return 1;
+}
+
+/**
+ * Handle the response to a "clear" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object
+ */
+DebugCommand.responseClear_ = function(msg) {
+ shell_.clearedBreakpoint(parseInt(msg.command.arguments.breakpoint));
+}
+
+/**
+ * Parses arguments to "frame" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseFrame_ = function(str) {
+ if (str.length > 0) {
+ var i = parseInt(str, 10);
+ if (i != str) {
+ return -1;
+ }
+ this.arguments = { 'number': i };
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "frame" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object
+ */
+DebugCommand.responseFrame_ = function(msg) {
+ body = msg.body;
+ loc = DebugCommand.getSourceLocation(body.func.script,
+ body.sourceLineText, body.line, body.func.name);
+ print("#" + body.index + " " + loc[0]);
+ print(loc[1]);
+ shell_.current_frame = body.index;
+ shell_.current_line = loc[2];
+ shell_.current_script = body.func.script;
+};
+
+/**
+ * Handle the response to a "args" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object (for "frame" command)
+ */
+DebugCommand.responseArgs_ = function(msg) {
+ DebugCommand.printVariables_(msg.body.arguments);
+}
+
+/**
+ * Handle the response to a "locals" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object (for "frame" command)
+ */
+DebugCommand.responseLocals_ = function(msg) {
+ DebugCommand.printVariables_(msg.body.locals);
+}
+
+DebugCommand.printVariables_ = function(variables) {
+ for (var i = 0; i < variables.length; i++) {
+ print(variables[i].name + " = " +
+ DebugCommand.toPreviewString_(variables[i].value));
+ }
+}
+
+DebugCommand.toPreviewString_ = function(value) {
+ // TODO(ericroman): pretty print arrays and objects, recursively.
+ // TODO(ericroman): truncate length of preview if too long?
+ if (value.type == "string") {
+ // Wrap the string in quote marks and JS-escape
+ return DebugCommand.stringToJSON(value.text);
+ }
+ return value.text;
+}
+
+/**
+ * Parses arguments to "scripts" command.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseScripts_ = function(str) {
+ return 1
+};
+
+/**
+ * Handle the response to a "scripts" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object
+ */
+DebugCommand.responseScripts_ = function(msg) {
+ scripts = msg.body;
+ shell_.scripts = [];
+ for (var i in scripts) {
+ var script = scripts[i];
+
+ // Add this script to the internal list of scripts.
+ shell_.scripts.push(script);
+
+ // Print result if this response was the result of a user command.
+ if (msg.command.from_user) {
+ var name = script.name;
+ if (name) {
+ if (script.lineOffset > 0) {
+ print(name + " (lines " + script.lineOffset + "-" +
+ (script.lineOffset + script.lineCount - 1) + ")");
+ } else {
+ print(name + " (lines " + script.lineCount + ")");
+ }
+ } else {
+ // For unnamed scripts (typically eval) display some source.
+ var sourceStart = script.sourceStart;
+ if (sourceStart.length > 40)
+ sourceStart = sourceStart.substring(0, 37) + '...';
+ print("[unnamed] (source:\"" + sourceStart + "\")");
+ }
+ }
+ }
+};
+
+/**
+ * Parses arguments to "source" command.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseSource_ = function(str) {
+ this.arguments = {};
+ if (this.current_frame > 0)
+ this.arguments.frame = this.current_frame;
+ if (str.length) {
+ var args = str.split(" ");
+ if (args.length == 1) {
+ // with 1 argument n, we print 10 lines starting at n
+ var num = parseInt(args[0]);
+ if (num > 0) {
+ this.arguments.fromLine = num - 1;
+ this.arguments.toLine = this.arguments.fromLine + 10;
+ } else {
+ return -1;
+ }
+ } else if (args.length == 2) {
+ // with 2 arguments x and y, we print from line x to line x + y
+ var from = parseInt(args[0]);
+ var len = parseInt(args[1]);
+ if (from > 0 && len > 0) {
+ this.arguments.fromLine = from - 1;
+ this.arguments.toLine = this.arguments.fromLine + len;
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ if (this.arguments.fromLine < 0)
+ return -1;
+ if (this.arguments.toLine <= this.arguments.fromLine)
+ return -1;
+ } else if (shell_.current_line > 0) {
+ // with no arguments, we print 11 lines with the current line as the center
+ this.arguments.fromLine =
+ Math.max(0, shell_.current_line - 6);
+ this.arguments.toLine = this.arguments.fromLine + 11;
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "source" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {Object} msg - the V8 debugger response object
+ */
+DebugCommand.responseSource_ = function(msg) {
+ var body = msg.body;
+ var from_line = parseInt(body.fromLine) + 1;
+ var source = body.source;
+ var lines = source.split('\n');
+ var maxdigits = 1 + Math.floor(DebugCommand.log10(from_line + lines.length))
+ for (var num in lines) {
+ // there's an extra newline at the end
+ if (num >= (lines.length - 1) && lines[num].length == 0)
+ break;
+ spacer = maxdigits - (1 + Math.floor(DebugCommand.log10(from_line)))
+ var line = "";
+ if (from_line == shell_.current_line) {
+ for (var i = 0; i < (maxdigits + 2); i++)
+ line += ">";
+ } else {
+ for (var i = 0; i < spacer; i++)
+ line += " ";
+ line += from_line + ": ";
+ }
+ line += lines[num];
+ print(line);
+ from_line++;
+ }
+};
+
+/**
+ * Parses arguments to "help" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return 0 for handled internally
+ */
+DebugCommand.parseHelp_ = function(str) {
+ DebugCommand.help(str);
+ return 0;
+};
+
+/**
+ * Takes argument and evaluates it in the context of the shell to allow commands
+ * to be escaped to the outer shell. Used primarily for development purposes.
+ * @see DebugCommand.commands
+ * @param {string} str The expression to be evaluated
+ * @return 0 for handled internally
+ */
+DebugCommand.parseShell_ = function(str) {
+ print(eval(str));
+ return 0;
+}
+
+DebugCommand.parseShellDebug_ = function(str) {
+ shell_.debug = !shell_.debug;
+ if (shell_.debug) {
+ print("shell debugging enabled");
+ } else {
+ print("shell debugging disabled");
+ }
+ return 0;
+}
+
+/**
+ * Parses a user-entered command string.
+ * @param {string} str The arguments to be parsed.
+ */
+DebugCommand.prototype.parseArgs_ = function(str) {
+ if (str.length)
+ str = DebugCommand.trim(str);
+ var cmd = DebugCommand.commands[this.user_command];
+ if (cmd) {
+ var parse = cmd['parse'];
+ if (parse == undefined) {
+ print('>>>can\'t find parse func for ' + this.user_command);
+ this.type = "error";
+ } else {
+ var ret = parse.call(this, str);
+ if (ret > 0) {
+ this.type = "request";
+ } else if (ret < 0) {
+ this.type = "handled";
+ DebugCommand.help(this.user_command);
+ }
+ }
+ } else {
+ this.type = "handled";
+ print('unknown command: ' + this.user_command);
+ DebugCommand.help();
+ }
+};
+
+/**
+ * Displays command help or all help.
+ * @param {string} opt_str Which command to print help for.
+ */
+DebugCommand.help = function(opt_str) {
+ if (opt_str) {
+ var cmd = DebugCommand.commands[opt_str];
+ var usage = cmd.usage;
+ print('usage: ' + usage);
+ // Print additional details for the command.
+ if (cmd.help) {
+ print(cmd.help);
+ }
+ } else {
+ if (shell_.running) {
+ print('Status: page is running');
+ } else {
+ print('Status: page is paused');
+ }
+ print('Available commands:');
+ for (var key in DebugCommand.commands) {
+ var cmd = DebugCommand.commands[key];
+ if (!cmd['hidden'] && (!shell_.running || cmd['while_running'])) {
+ var usage = cmd.usage;
+ print(' ' + usage);
+ }
+ }
+ }
+};
+
+/**
+ * Valid commands, their argument parser and their associated usage text.
+ */
+DebugCommand.commands = {
+ 'args': { 'parse': DebugCommand.prototype.parseArgsAndLocals_,
+ 'usage': 'args',
+ 'help': 'summarize the arguments to the current function.',
+ 'response': DebugCommand.responseArgs_ },
+ 'break': { 'parse': DebugCommand.prototype.parseBreak_,
+ 'response': DebugCommand.responseBreak_,
+ 'usage': 'break [location] <condition>',
+ 'help': 'location is one of <function> | <script:function> | <script:line> | <script:line:pos>',
+ 'while_running': true },
+ 'break_info': { 'parse': DebugCommand.prototype.parseBreakInfo_,
+ 'usage': 'break_info [breakpoint #]',
+ 'help': 'list the current breakpoints, or the details on a single one',
+ 'while_running': true },
+ 'backtrace': { 'parse': DebugCommand.prototype.parseBacktrace_,
+ 'response': DebugCommand.responseBacktrace_,
+ 'usage': 'backtrace [from frame #] [to frame #]' },
+ 'clear': { 'parse': DebugCommand.prototype.parseClearCommand_,
+ 'response': DebugCommand.responseClear_,
+ 'usage': 'clear <breakpoint #>',
+ 'while_running': true },
+ 'continue': { 'parse': DebugCommand.parseSimpleCommand_,
+ 'usage': 'continue' },
+ 'frame': { 'parse': DebugCommand.prototype.parseFrame_,
+ 'response': DebugCommand.responseFrame_,
+ 'usage': 'frame <frame #>' },
+ 'help': { 'parse': DebugCommand.parseHelp_,
+ 'usage': 'help [command]',
+ 'while_running': true },
+ 'locals': { 'parse': DebugCommand.prototype.parseArgsAndLocals_,
+ 'usage': 'locals',
+ 'help': 'summarize the local variables for current frame',
+ 'response': DebugCommand.responseLocals_ },
+ 'next': { 'parse': DebugCommand.prototype.parseNext_,
+ 'usage': 'next' } ,
+ 'print': { 'parse': DebugCommand.prototype.parsePrint_,
+ 'response': DebugCommand.responsePrint_,
+ 'usage': 'print <expression>',
+ 'while_running': true },
+ 'scripts': { 'parse': DebugCommand.prototype.parseScripts_,
+ 'response': DebugCommand.responseScripts_,
+ 'usage': 'scripts',
+ 'while_running': true },
+ 'source': { 'parse': DebugCommand.prototype.parseSource_,
+ 'response': DebugCommand.responseSource_,
+ 'usage': 'source [from line] | [<from line> <num lines>]' },
+ 'step': { 'parse': DebugCommand.prototype.parseStep_,
+ 'usage': 'step' },
+ 'stepout': { 'parse': DebugCommand.prototype.parseStepOut_,
+ 'usage': 'stepout' },
+ // local eval for debugging - remove this later
+ 'shell': { 'parse': DebugCommand.parseShell_,
+ 'usage': 'shell <expression>',
+ 'while_running': true,
+ 'hidden': true },
+ 'shelldebug': { 'parse': DebugCommand.parseShellDebug_,
+ 'usage': 'shelldebug',
+ 'while_running': true,
+ 'hidden': true },
+};
+
+
+/**
+ * Debug shell using the new JSON protocol
+ * @param {Object} tab - which tab is to be debugged. This is an internal
+ * Chrome object.
+ * @constructor
+ */
+function DebugShell(tab) {
+ this.tab = tab;
+ this.tab.attach();
+ this.ready = true;
+ this.running = true;
+ this.current_command = undefined;
+ this.pending_commands = [];
+ this.debug = false;
+ this.last_msg = undefined;
+ this.last_command = undefined;
+ this.current_line = -1;
+ this.current_pos = -1;
+ this.current_frame = 0;
+ this.current_script = undefined;
+ this.scripts = [];
+
+ // Mapping of breakpoints id --> info.
+ // Must use numeric keys.
+ this.breakpoints = [];
+};
+
+DebugShell.prototype.set_ready = function(ready) {
+ if (ready != this.ready) {
+ this.ready = ready;
+ chrome.setDebuggerReady(this.ready);
+ }
+};
+
+DebugShell.prototype.set_running = function(running) {
+ if (running != this.running) {
+ this.running = running;
+ chrome.setDebuggerBreak(!this.running);
+ }
+};
+
+/**
+ * Execute a constructed DebugCommand object if possible, otherwise pend.
+ * @param cmd {DebugCommand} - command to execute
+ */
+DebugShell.prototype.process_command = function(cmd) {
+ if (this.current_command) {
+ this.pending_commands.push(cmd);
+ dprint("pending command: " + DebugCommand.toJSON(cmd));
+ } else if (cmd.type == "shell") {
+ if (cmd.user_command == "break") {
+ if (this.running) {
+ this.tab.debugBreak();
+ this.set_ready(false);
+ } else {
+ print(">>already paused");
+ }
+ }
+ this.last_command = cmd;
+ } else if (cmd.type == "request") {
+ // If the page is running, then the debugger isn't listening to certain
+ // requests.
+ var cmd_info = DebugCommand.commands[cmd.user_command];
+ if (this.running && !cmd_info['while_running']) {
+ print(cmd.user_command + " can only be run while paused");
+ } else {
+ this.current_command = cmd;
+ cmd.sendToDebugger(this.tab);
+ this.set_ready(false);
+ }
+ }
+ this.last_command = cmd;
+};
+
+/**
+ * Handle a break event from the debugger.
+ * @param msg {Object} - event protocol message to handle
+ */
+DebugShell.prototype.event_break = function(msg) {
+ this.current_frame = 0;
+ this.set_running(false);
+ this.set_ready(true);
+ if (msg.body) {
+ var body = msg.body;
+ this.current_script = body.script;
+ var loc = DebugCommand.getSourceLocation(body.script,
+ body.sourceLineText, body.sourceLine, body.invocationText);
+ var location = loc[0];
+ var source = loc[1];
+ this.current_line = loc[2];
+ if (msg.body.breakpoints) {
+ var breakpoints = msg.body.breakpoints;
+ print("paused at breakpoint " + breakpoints.join(",") + ": " +
+ location);
+ for (var i = 0; i < breakpoints.length; i++)
+ this.didHitBreakpoint(parseInt(breakpoints[i]));
+ } else if (body.scriptData == "") {
+ print("paused");
+ } else {
+ // step, stepout, next, "break" and a "debugger" line in the code
+ // are all treated the same (they're not really distinguishable anyway)
+ if (location != this.last_break_location) {
+ // We only print the location (function + script) when it changes,
+ // so as we step, you only see the source line when you transition
+ // to a new script and/or function.
+ print(location);
+ }
+ }
+ if (source)
+ print(source);
+ this.last_break_location = location;
+ }
+};
+
+/**
+ * Handle an exception event from the debugger.
+ * @param msg {Object} - event protocol message to handle
+ */
+DebugShell.prototype.event_exception = function(msg) {
+ this.set_running(false);
+ this.set_ready(true);
+ if (msg.body) {
+ if (msg.body["uncaught"]) {
+ print("uncaught exception " + msg.body["exception"].text);
+ } else {
+ print("paused at exception " + msg.body["exception"].text);
+ }
+ }
+};
+
+DebugShell.prototype.matchScript = function(script_match, line) {
+ var script = null;
+ // In the v8 debugger, all scripts have a name, line offset and line count
+ // Script names are usually URLs which are a pain to have to type again and
+ // again, so we match the tail end of the script name. This makes it easy
+ // to type break foo.js:23 rather than
+ // http://www.foo.com/bar/baz/quux/test/foo.js:23. In addition to the tail
+ // of the name we also look at the lines the script cover. If there are
+ // several scripts with the same tail including the requested line we match
+ // the first one encountered.
+ // TODO(sgjesse) Find how to handle several matching scripts.
+ var candidate_scripts = [];
+ for (var i in this.scripts) {
+ if (this.scripts[i].name &&
+ this.scripts[i].name.indexOf(script_match) >= 0) {
+ candidate_scripts.push(this.scripts[i]);
+ }
+ }
+ for (var i in candidate_scripts) {
+ var s = candidate_scripts[i];
+ var from = s.lineOffset;
+ var to = from + s.lineCount;
+ if (from <= line && line < to) {
+ script = s;
+ break;
+ }
+ }
+ if (script)
+ return script;
+ else
+ return null;
+}
+
+// The Chrome Subshell interface requires:
+// prompt(), command(), response(), exit() and on_disconnect()
+
+/**
+ * Called by Chrome Shell to get a prompt string to display.
+ */
+DebugShell.prototype.prompt = function() {
+ if (this.current_command)
+ return '';
+ if (!this.running)
+ return 'v8(paused)> ';
+ else
+ return 'v8(running)> ';
+};
+
+/**
+ * Called by Chrome Shell when command input has been received from the user.
+ */
+DebugShell.prototype.command = function(str) {
+ if (this.tab) {
+ str = DebugCommand.trim(str);
+ if (str.length) {
+ var cmd = new DebugCommand(str);
+ cmd.from_user = true;
+ this.process_command(cmd);
+ }
+ } else {
+ print(">>not connected to a tab");
+ }
+};
+
+/**
+ * Called by Chrome Shell when a response to a previous command has been
+ * received.
+ */
+DebugShell.prototype.response = function(str) {
+ var msg;
+ try {
+ dprint("received: " + str);
+ msg = eval('(' + str + ')');
+ this.last_msg = msg;
+ } catch (error) {
+ print(error.toString(), str);
+ return;
+ }
+ if (msg.type == "event") {
+ ev = msg["event"]
+ if (ev == "break") {
+ this.event_break(msg);
+ } else if (ev == "exception") {
+ this.event_exception(msg);
+ } else if (ev == "attach") {
+ var title = this.tab.title;
+ if (!title)
+ title = "Untitled";
+ print('attached to ' + title);
+ // on attach, we update our current script list
+ var cmd = new DebugCommand("scripts");
+ cmd.from_user = false;
+ this.process_command(cmd);
+ }
+ } else if (msg.type == "response") {
+ if (msg.request_seq != undefined) {
+ if (!this.current_command || this.current_command.seq != msg.request_seq){
+ throw("received response to unknown command " + DebugCommand.toJSON(msg));
+ }
+ } else {
+ // TODO(erikkay): should we reject these when they happen?
+ print(">>no request_seq in response " + DebugCommand.toJSON(msg));
+ }
+ var cmd = DebugCommand.commands[this.current_command.user_command]
+ msg.command = this.current_command;
+ this.current_command = null
+ if (msg.running != undefined) {
+ this.set_running(msg.running);
+ }
+ if (!msg['success']) {
+ print(msg['message']);
+ } else {
+ var response = cmd['response'];
+ if (response != undefined) {
+ response.call(this, msg);
+ }
+ }
+ this.set_ready(true);
+ if (this.pending_commands.length) {
+ this.process_command(this.pending_commands.shift());
+ }
+ }
+};
+
+/**
+ * Called when a breakpoint has been set.
+ * @param {BreakpointInfo} info - details of breakpoint set.
+ */
+DebugShell.prototype.addedBreakpoint = function(info) {
+ print("set breakpoint #" + info.id);
+ this.breakpoints[info.id] = info;
+}
+
+/**
+ * Called when a breakpoint has been cleared.
+ * @param {int} id - the breakpoint number that was cleared.
+ */
+DebugShell.prototype.clearedBreakpoint = function(id) {
+ assertIsNumberType(id, "clearedBreakpoint called with invalid id");
+
+ print("cleared breakpoint #" + id);
+ delete this.breakpoints[id];
+}
+
+/**
+ * Called when a breakpoint has been reached.
+ * @param {int} id - the breakpoint number that was hit.
+ */
+DebugShell.prototype.didHitBreakpoint = function(id) {
+ assertIsNumberType(id, "didHitBreakpoint called with invalid id");
+
+ var info = this.breakpoints[id];
+ if (!info)
+ throw "Could not find breakpoint #" + id;
+
+ info.hit_count ++;
+}
+
+/**
+ * Print a summary of the specified breakpoints.
+ *
+ * @param {Array<BreakpointInfo>} breakpointsToPrint - List of breakpoints. The
+ * index is unused (id is determined from the info).
+ */
+DebugShell.printBreakpoints_ = function(breakpoints) {
+ // TODO(ericroman): this would look much nicer if we could output as an HTML
+ // table. I tried outputting as formatted text table, but this looks aweful
+ // once it triggers wrapping (which is very likely if the target is a script)
+
+ // Output as a comma separated list of key=value
+ for (var i in breakpoints) {
+ var b = breakpoints[i];
+ var props = ["id", "hit_count", "type", "target", "line", "position",
+ "condition"];
+ var propertyList = [];
+ for (var i = 0; i < props.length; i++) {
+ var prop = props[i];
+ var val = b[prop];
+ if (val != undefined)
+ propertyList.push(prop + "=" + val);
+ }
+ print(propertyList.join(", "));
+ }
+}
+
+/**
+ * Called by Chrome Shell when the outer shell is detaching from debugging
+ * this tab.
+ */
+DebugShell.prototype.exit = function() {
+ if (this.tab) {
+ this.tab.detach();
+ this.tab = null;
+ }
+};
+
+/**
+ * Called by the Chrome Shell when the tab that the shell is debugging
+ * went away.
+ */
+DebugShell.prototype.on_disconnect = function() {
+ print(">>lost connection to tab");
+ this.tab = null;
+};
+
+
+/**
+ * Structure that holds the details about a breakpoint.
+ * @constructor
+ *
+ * @param {int} id - breakpoint number
+ * @param {string} type - "script" or "function"
+ * @param {string} target - either a function name, or script url
+ * @param {int} line - line number in the script, or undefined
+ * @param {int} position - column in the script, or undefined
+ * @param {string} condition - boolean expression, or undefined
+ */
+function BreakpointInfo(id, type, target, line, position, condition) {
+ this.id = id;
+ this.type = type;
+ this.target = target;
+
+ if (line != undefined)
+ this.line = line;
+ if (position != undefined)
+ this.position = position;
+ if (condition != undefined)
+ this.condition = condition;
+
+ this.hit_count = 0;
+
+ // Check that the id is numeric, otherwise will run into problems later
+ assertIsNumberType(this.id, "id is not a number");
+}
+
+/**
+ * Global function to enter the debugger using DebugShell.
+ * User can access this in the external shell by simply typing "debug()".
+ * This is called by the Chrome Shell when the shell attaches to a tab.
+ * @param {Object} opt_tab - which tab is to be debugged. This is an internal
+ * Chrome object.
+ */
+function debug(opt_tab) {
+ shell(new DebugShell(opt_tab || chrome.browser[0].tab[0]));
+};
+
+/**
+ * Print debugging message when DebugShell's debug flag is true.
+ */
+function dprint(str) {
+ if (shell_ && shell_.debug) {
+ print(str);
+ }
+};
+
+/**
+ * Helper that throws error if x is not a number
+ * @param x {object} - object to test type of
+ * @param error_message {string} - error to throw on failure
+ */
+function assertIsNumberType(x, error_message) {
+ if (typeof x != "number")
+ throw error_message;
+}
diff --git a/chrome/browser/resources/gear.png b/chrome/browser/resources/gear.png
new file mode 100644
index 0000000..3dce105
--- /dev/null
+++ b/chrome/browser/resources/gear.png
Binary files differ
diff --git a/chrome/browser/resources/help.gif b/chrome/browser/resources/help.gif
new file mode 100644
index 0000000..f49c094
--- /dev/null
+++ b/chrome/browser/resources/help.gif
Binary files differ
diff --git a/chrome/browser/resources/incognito_tab.html b/chrome/browser/resources/incognito_tab.html
new file mode 100644
index 0000000..6d34646
--- /dev/null
+++ b/chrome/browser/resources/incognito_tab.html
@@ -0,0 +1,31 @@
+<html id="t" jsvalues="dir:textdirection">
+<head>
+<title jscontent="title"></title>
+<style type="text/css">
+body {
+ margin:10px 8px 10px 8px;
+}
+.icon {
+ float:right;
+ margin:0px 6px 0px 3px;
+}
+.content {
+ -webkit-border-radius: 5px 5px;
+ background-color:#eee;
+ color:black;
+ padding:10px 10px 10px 10px;
+ font-family:arial;
+ font-size:84%;
+ max-width:600px;
+ margin-left:auto;
+ margin-right:auto;
+}
+</style>
+</head>
+<body>
+<div class="content">
+ <img src="../../app/theme/otr_icon_standalone.png" class="icon" />
+ <span jseval="this.innerHTML = $this.content;"></span>
+</div>
+</body>
+</html>
diff --git a/chrome/browser/resources/new_tab.html b/chrome/browser/resources/new_tab.html
new file mode 100644
index 0000000..133b8b6
--- /dev/null
+++ b/chrome/browser/resources/new_tab.html
@@ -0,0 +1,624 @@
+<html id="t" jsvalues="dir:textdirection;newsession:newsession">
+<!--
+ This page is optimized for perceived performance. Our enemies are the time
+ taken for the backend to generate our data, and the time taken to parse
+ and render the starting HTML/CSS content of the page. This page is
+ designed to let Chrome do both of those things in parallel.
+
+ 1. Defines temporary content callback functions
+ 2. Fires off requests for content (these can come back 20-150ms later)
+ 3. Defines basic functions (handlers)
+ 4. Renders a fast-parse hard-coded version of itself (this can take 20-50ms)
+ 5. Defines the full content-rendering functions
+
+ If the requests for content come back before the content-rendering functions
+ are defined, the data is held until those functions are defined.
+-->
+<script type="text/javascript">
+/* Logging info for benchmarking purposes. */
+var log = [];
+function logEvent(name) {
+ log.push([name, new Date().getTime()]);
+}
+
+// Basic functions to send, receive, store and process the data from our
+// backend.
+var unprocessedData = {
+ mostVisitedPages : false,
+ searchURLs : false,
+ recentlyBookmarked : false,
+ recentlyClosedTabs : false
+}
+
+var renderFunctionsDefined = false;
+
+/**
+ * If the functions that can render content are defined, render
+ * the content for any data we've received so far.
+ */
+function processData() {
+ if (renderFunctionsDefined) {
+ if (unprocessedData.mostVisitedPages) {
+ renderMostVisitedPages(unprocessedData.mostVisitedPages);
+ unprocessedData.mostVisitedPages = false;
+ }
+ if (unprocessedData.searchURLs) {
+ renderSearchURLs(unprocessedData.searchURLs);
+ unprocessedData.searchURLs = false;
+ }
+ if (unprocessedData.recentlyBookmarked) {
+ renderRecentlyBookmarked(unprocessedData.recentlyBookmarked);
+ unprocessedData.recentlyBookmarked = false;
+ }
+ if (unprocessedData.recentlyClosedTabs) {
+ renderRecentlyClosedTabs(unprocessedData.recentlyClosedTabs);
+ unprocessedData.recentlyClosedTabs = false;
+ }
+ }
+}
+
+function mostVisitedPages(data) {
+ logEvent('received most visited pages');
+ unprocessedData.mostVisitedPages = data;
+ processData();
+}
+
+function searchURLs(data) {
+ logEvent('received search URLs');
+ unprocessedData.searchURLs = data;
+ processData();
+}
+
+function recentlyBookmarked(data) {
+ logEvent('received recently bookmarked data');
+ unprocessedData.recentlyBookmarked = data;
+ processData();
+}
+
+function recentlyClosedTabs(data) {
+ logEvent('received recently closed tabs');
+ unprocessedData.recentlyClosedTabs = data;
+ processData();
+}
+
+chrome.send("getMostVisited");
+chrome.send("getMostSearched");
+chrome.send("getRecentlyBookmarked");
+chrome.send("getRecentlyClosedTabs");
+
+function handleWindowResize() {
+ if (!document.body || document.body.clientWidth < 10) {
+ // We're probably a background tab, so don't do anything.
+ return;
+ }
+
+ if (document.body.className == 'small' && document.body.clientWidth >= 885) {
+ document.body.className = '';
+ } else if (document.body.className == '' && document.body.clientWidth <= 865) {
+ document.body.className = 'small';
+ }
+}
+
+function handleInputFocus() {
+ if (!this.deftext) {
+ this.deftext = this.value;
+ }
+
+ if (this.value == this.deftext) {
+ this.className = '';
+ this.value = '';
+ }
+}
+
+function handleInputBlur() {
+ if (!this.value) {
+ this.className = 'hint';
+ this.value = this.deftext;
+ }
+}
+
+function handleDOMContentLoaded() {
+ logEvent('domcontentloaded fired');
+
+ if (document.getElementById('motd').innerHTML) {
+ document.getElementById('motd').style.display = 'block';
+ }
+}
+
+logEvent('log start');
+</script>
+<head>
+<title jscontent="title"></title>
+<style type="text/css">
+body {
+ font-family:arial;
+ background-color:white;
+ font-size:84%;
+ margin:0px;
+}
+html[newsession='true'] #main {
+ opacity:0.0;
+ -webkit-transition:all 0.4s;
+}
+html[newsession='true'] #main.visible {
+ /* unfortunately, 1.0 results in no animation */
+ opacity:0.999;
+}
+#main {
+ margin-left:auto;
+ margin-right:auto;
+ margin-top:10px;
+}
+td {
+ font-size:84%;
+}
+form {
+ padding: 0;
+ margin: 0;
+}
+.section {
+ padding:3px 0px 5px 0px;
+ margin-bottom:30px;
+}
+.section-title {
+ color:#000;
+ line-height:19pt;
+ font-size:110%;
+ font-weight:bold;
+ margin-bottom:4px;
+}
+#mostvisitedsection {
+ margin:0px 5px 0px 0px;
+}
+#mostvisited td {
+ padding:0px 10px 10px 0px;
+}
+html[dir='rtl'] #mostvisited td {
+ padding:0px 0px 10px 10px;
+}
+.most-visited-text {
+ width:548px; /* thumbnail + td * 3 - 2*padding - 2*margin */
+ padding:20px;
+ margin:15px;
+ background-color:white;
+ -webkit-box-shadow: 5px 5px 10px #ccc;
+ -webkit-transition:all 0.12s;
+}
+#motd {
+ background-color:#ffc;
+ padding:5px;
+ margin-bottom:9px;
+ width:610px;
+ -webkit-transition:all 0.12s;
+}
+.thumbnail-title {
+ background-image:url(chrome-resource://favicon/);
+ display:block;
+ background-repeat:no-repeat;
+ background-size:16px;
+ background-position:0px 1px;
+ width:172px; /* thumbnail - padding */
+ margin-top:6px; /* line up favicons with search favicons */
+ padding:1px 0px 4px 22px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-decoration:none;
+ -webkit-transition:all 0.12s;
+}
+html[dir='rtl'] .thumbnail-title {
+ background-position:right;
+ padding-left:0px;
+ padding-right:22px;
+}
+.thumbnail {
+ width:195px;
+ height:136px;
+ border:1px solid #ccc;
+ background-color:#eee;
+ -webkit-transition:all 0.12s;
+}
+a.thumbnail {
+ border:1px solid #abe;
+}
+
+.small #motd {
+ width:480px;
+}
+.small .thumbnail-title {
+ width:127px;
+}
+.small .thumbnail {
+ width:150px;
+ height:113px;
+}
+.small .most-visited-text {
+ width:430px;
+ padding:15px;
+ margin:12px;
+}
+
+.recent-bookmark {
+ display:block;
+ background-repeat:no-repeat;
+ background-size:16px;
+ background-position:0px 1px;
+ padding:1px 0px 0px 22px;
+ margin:3px 0px 3px 0px;
+ min-height:16pt;
+ line-height:16px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-decoration:underline;
+}
+html[dir='rtl'] .recent-bookmark {
+ background-position:right;
+ padding-left:0px;
+ padding-right:22px;
+}
+a {
+ color:#0000cc;
+ text-decoration:underline;
+ white-space: nowrap;
+}
+a.manage {
+ color:#77c;
+ margin-left: 5px;
+ margin-right: 5px;
+ font-size:84%;
+ line-height:19pt;
+ text-decoration:underline;
+}
+html[dir='rtl'] #managesearcheslink {
+ float: left;
+}
+.sidebar {
+ width: 207px;
+ padding:3px 10px 3px 9px;
+ -webkit-border-radius:5px 5px;
+ margin-bottom:10px;
+}
+#searches {
+ background-color:#e1ecfe;
+}
+#recentlyBookmarked {
+ background-color:#e1ecfe;
+}
+#recentlyClosedTabs {
+ background-color:#fff1a8;
+}
+#searches input {
+ border:1px solid #7f9db9;
+ background-repeat: no-repeat;
+ background-position:4px center;
+ padding-left: 23px;
+ min-height:24px;
+ width:206px;
+ margin-bottom:8px;
+ display:block;
+}
+html[dir='rtl'] #searches input {
+ background-position: right;
+ padding-right: 23px;
+}
+#searches input.hint {
+ color:#aaa;
+}
+.footer {
+ border-top:1px solid #ccc;
+ padding-top:4px;
+ font-size:8pt;
+}
+</style>
+</head>
+<body onload="logEvent('body onload fired');">
+<script>
+// We apply the size class here so that we don't trigger layout animations onload.
+handleWindowResize();
+window.addEventListener('resize', handleWindowResize, true);
+document.addEventListener('DOMContentLoaded', handleDOMContentLoaded);
+</script>
+
+<table id="main" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td valign="top">
+ <div id="mostvisitedsection" class="section">
+ <div id="motd" jscontent="motd" style="display:none;"></div>
+ <div id="mostvisited" style="position:relative;">
+ <div class="section-title" jscontent="mostvisited"></div>
+ <div id="mostvisitedintro" style="display:none;">
+ <div class="most-visited-text" style="position:absolute;" jseval="this.innerHTML = $this.mostvisitedintro;"></div>
+ <table>
+ <tr>
+ <td><div class="thumbnail">&nbsp;</div></td>
+ <td><div class="thumbnail"></div></td>
+ <td><div class="thumbnail">&nbsp;</div></td>
+ </tr>
+ <tr>
+ <td><div class="thumbnail">&nbsp;</div></td>
+ <td><div class="thumbnail"></div></td>
+ <td><div class="thumbnail">&nbsp;</div></td>
+ </tr>
+ </table>
+ </div>
+ <table id="mostvisitedtable">
+ <!-- This content forces the view to the correct width and provides a
+ preview of what's to load to reduce white-flash. Users who get
+ the mostvisitedintro will see a brief flash of this content. We
+ only use one row so that we may avoid flashing extra rows when
+ the user has only one row of items -->
+ <tr>
+ <td>
+ <div class="thumbnail-title">&nbsp;</div>
+ <div class="thumbnail"></div>
+ </td>
+ <td>
+ <div class="thumbnail-title">&nbsp;</div>
+ <div class="thumbnail"></div>
+ </td>
+ <td>
+ <div class="thumbnail-title">&nbsp;</div>
+ <div class="thumbnail"></div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <a href="#"
+ class="manage"
+ onclick="chrome.send('showHistoryPage'); return false">
+ <span jscontent="showhistory"></span> &raquo;</a>
+ </div>
+ </td>
+ <td valign="top" width="230">
+ <div align="right">
+ <img src="../../app/theme/product_logo.png"
+ width="145" height="52" style="padding-bottom:8px;" />
+ </div>
+ <div id="searches" class="sidebar">
+ <div class="section-title" jscontent="searches"></div>
+ <form onsubmit="chrome.send('searchHistoryPage', [this.search.value]); return false;">
+ <input type="text" class="hint"
+ name="search"
+ style="background-image:url(chrome-resource://favicon/);"
+ jsvalues="value:searchhistory"
+ onfocus="handleInputFocus.apply(this);"
+ onblur="handleInputBlur.apply(this);" />
+ </form>
+ <div id='searches-entries'></div>
+ </div>
+
+ <div id="recentlyBookmarked" class="sidebar" style="display:none">
+ <span class="section-title" jscontent="bookmarks"></span>
+ </div>
+
+ <div id="recentlyClosedTabs" class="sidebar" style="display:none">
+ <div class="section-title" jscontent="closedtabs"></div>
+ <div id="recentlyClosedContainer"></div>
+ </div>
+ </td>
+ </tr>
+</table>
+
+<script type="text/javascript">
+logEvent('start of second script block');
+
+/* Return a DOM element with tag name |elem| and attributes |attrs|. */
+function DOM(elem, attrs) {
+ var elem = document.createElement(elem);
+ for (var attr in attrs) {
+ elem[attr] = attrs[attr];
+ }
+ return elem;
+}
+
+/* Return the DOM element for a "most visited" entry.
+ |page| should be an object with "title" and "url" fields. */
+function makeMostVisitedDOM(page) {
+ /* The HTML we want looks like this:
+ <a class="most-visited-item" href="URL" title="gmail.com">
+ <div class="thumbnail-title" style="background-image:url(faviconurl);">gmail.com</div>
+ <img class="thumbnail" style="background-image:url(thumbnailurl);" />
+ </a>
+ */
+ var root = DOM('a', {href:page.url, className:'most-visited-item', title:page.title});
+
+ /* Create the thumbnail */
+ var img_thumbnail = DOM('img', {className:'thumbnail'});
+ img_thumbnail.setAttribute('onload', "logEvent('image loaded');");
+ img_thumbnail.src = 'chrome-resource://thumb/' + page.url;
+
+ /* Create the title */
+ var div_title = DOM('div', {className:'thumbnail-title'});
+ div_title.style.backgroundImage =
+ 'url("chrome-resource://favicon/' + page.url + '")';
+ div_title.appendChild(document.createTextNode(page.title));
+
+ root.appendChild(div_title);
+ root.appendChild(img_thumbnail);
+
+ return root;
+}
+
+/* This function is called by the browser with the most visited pages list.
+ |pages| is a list of page objects, which have url and title attributes. */
+function renderMostVisitedPages(pages) {
+ logEvent('renderMostVisitedPages called: ' + pages.length);
+
+ document.getElementById("main").className = 'visible';
+ var table = document.getElementById("mostvisitedtable");
+ table.innerHTML = '';
+
+ // Show the most visited helptext if most visited is still useless. This is
+ // a crappy heuristic.
+ if (pages.length < 3) {
+ document.getElementById("mostvisitedintro").style.display = "block";
+ return;
+ }
+
+ document.getElementById('mostvisitedintro').style.display = 'none';
+
+ // Create the items and add them to rows.
+ var rows = [];
+ var rowNum = -1;
+ for (var i = 0, page; page = pages[i]; ++i) {
+ if (i % 3 == 0) {
+ rowNum += 1;
+ rows[rowNum] = DOM('tr', {});
+ }
+
+ var dom = makeMostVisitedDOM(page);
+
+ var cell = DOM('td');
+ cell.appendChild(dom);
+
+ rows[rowNum].appendChild(cell);
+
+ logEvent('mostVisitedPage : ' + i);
+ }
+
+ // Add the rows to the table.
+ for (var i = 0, row; row = rows[i]; i++) {
+ table.appendChild(row);
+ }
+
+ logEvent('renderMostVisitedPages done');
+}
+
+function makeSearchURL(url) {
+ /* The HTML we want looks like this:
+ <form>
+ <input type="text" class="hint"
+ style="background-image:url(chrome-resource://favicon/"+url+");"
+ value="Search Wikipedia"
+ onfocus="handleInputFocus();"
+ onblur="handleInputBlur();" />
+ </form>
+ */
+ var input = DOM('input', {type:'text',
+ className:'hint',
+ value:url.short_name});
+ input.keyword = url.keyword;
+
+ if (url.favIconURL) {
+ input.style.backgroundImage =
+ 'url("chrome-resource://favicon/iconurl/' + url.favIconURL + '")';
+ } else {
+ input.style.backgroundImage =
+ 'url("chrome-resource://favicon/http://' + url.short_name + '")';
+ }
+
+ input.onfocus = handleInputFocus;
+ input.onblur = handleInputBlur;
+
+ var form = DOM('form');
+ form.onsubmit = function() {
+ chrome.send('doSearch', [input.keyword, input.value]);
+ return false;
+ };
+ form.appendChild(input);
+
+ return form;
+}
+
+/* This function is called by the browser when the list of search URLs is
+ available. |urls| is a list of objects with |name| attributes. */
+function renderSearchURLs(urls) {
+ logEvent('renderSearchURLs called: ' + urls.length);
+ var container = document.getElementById('searches-entries');
+ container.innerHTML = ''; // Clear out any previous contents.
+ if (urls.length > 0) {
+ document.getElementById('searches').style.display = 'block';
+ for (var i = 0; i < urls.length; ++i) {
+ container.appendChild(makeSearchURL(urls[i]));
+ }
+ }
+
+ logEvent('renderSearchURLs done');
+}
+
+/* This function is called by the browser when the list of recently bookmarked
+ URLs is available. |entries| is a list of objects with title and url
+ attributes. */
+function renderRecentlyBookmarked(entries) {
+ logEvent('renderRecentlyBookmarked called: ' + entries.length);
+ var container = document.getElementById('recentlyBookmarked');
+
+ if (entries.length > 0) {
+ container.style.display = 'block';
+ for (var i = 0, entry = entries[0]; entry = entries[i]; ++i) {
+ var link = DOM('a', {href: entry.url, className:'recent-bookmark', title:entry.title});
+ link.style.backgroundImage =
+ 'url("chrome-resource://favicon/' + entry.url + '")';
+ link.appendChild(document.createTextNode(entry.title));
+ container.appendChild(link);
+ }
+ }
+
+ logEvent('renderRecentlyBookmarked done');
+}
+
+/* This function adds incoming information about tabs to the new tab UI. */
+function renderRecentlyClosedTabs(entries) {
+ logEvent('renderRecentlyClosedTabs begin');
+ var section = document.getElementById('recentlyClosedTabs');
+ var container = document.getElementById('recentlyClosedContainer');
+
+ /* recentlyClosedTabs is called on every internal event which
+ affects tab history to make sure things are up to
+ date. Therefore, reset the recentlyClosedTabs state on every
+ call. */
+ section.style.display = 'none';
+ while(container.hasChildNodes()) {
+ container.removeChild(container.firstChild);
+ }
+
+ if (entries.length > 0) {
+ section.style.display = 'block';
+
+ for (var i = 0; entry = entries[i]; ++i) {
+ var link = DOM('a', {href:entry.url, className:'recent-bookmark', title:entry.title});
+
+ link.onclick = function(sessionId) {
+ return function() {
+ /* This is a hack because chrome.send is hardcoded to only
+ accept arrays of strings. */
+ chrome.send('reopenTab', [sessionId.toString()]);
+ return false;
+ }
+ }(entry.sessionId);
+
+ link.style.backgroundImage = 'url("chrome-resource://favicon/' + entry.url + '")';
+ link.appendChild(document.createTextNode(entry.title));
+ container.appendChild(link);
+ }
+ }
+
+ logEvent('renderRecentlyClosedTabs done');
+}
+
+function viewLog() {
+ var lines = [];
+ var start = log[0][1];
+
+ for (var i = 0; i < log.length; i++) {
+ lines.push((log[i][1] - start) + ': ' + log[i][0]);
+ }
+
+ var lognode = document.createElement('pre');
+ lognode.appendChild(document.createTextNode(lines.join("\n")));
+ document.body.appendChild(lognode);
+}
+
+logEvent('end of second script block');
+
+// We've got all the JS we need, render any unprocessed data.
+renderFunctionsDefined = true;
+processData();
+
+// In case renderMostVisitedItems doesn't come back quickly enough, begin
+// the first-run fade-in. If it has started or if this is not a first
+// run new tab, this will be a no-op.
+setTimeout(function(){document.getElementById('main').className = 'visible'},
+ 1000);
+</script>
+</body>
+</html>
diff --git a/chrome/browser/resources/phishing_icon.png b/chrome/browser/resources/phishing_icon.png
new file mode 100644
index 0000000..b23e76b
--- /dev/null
+++ b/chrome/browser/resources/phishing_icon.png
Binary files differ
diff --git a/chrome/browser/resources/safe_browsing_malware_block.html b/chrome/browser/resources/safe_browsing_malware_block.html
new file mode 100644
index 0000000..1e815ea
--- /dev/null
+++ b/chrome/browser/resources/safe_browsing_malware_block.html
@@ -0,0 +1,102 @@
+<html id="template_root" jsvalues="dir:textdirection">
+<head>
+<title jscontent="title"></title>
+<style type="text/css">
+body {
+ background-color:#500;
+ font-family:arial;
+ margin:0px;
+}
+.background {
+ position:absolute;
+ width:100%;
+ height:100%;
+}
+.cell {
+ padding:40px;
+}
+.box {
+ width:80%;
+ background-color:white;
+ color:black;
+ font-size:10pt;
+ line-height:16pt;
+ text-align:left;
+ padding:20px;
+ position:relative;
+ -webkit-box-shadow:3px 3px 8px #200;
+ -webkit-border-radius:5px;
+}
+html[dir='rtl'] .box {
+ text-align:right;
+}
+
+.icon {
+ position:absolute;
+}
+.title {
+ margin:0px 87px 0px;
+ font-size:18pt;
+ margin-bottom:6pt;
+ font-weight:bold;
+ color:#660000;
+}
+.main {
+ margin:0px 90px 0px;
+}
+.submission {
+ margin:15px 5px 15px 0px;
+ padding:0px;
+}
+input {
+ margin:0px;
+}
+.proceedbutton {
+}
+.helpbutton {
+ float:right;
+}
+.example {
+ margin: 30px 90px 0px;
+ border-top:1px solid #ccc;
+ padding-top:6px;
+}
+.moreinfotitle {
+ margin-left:5px;
+ margin-right:5px;
+}
+</style>
+
+<script>
+ function sendCommand(cmd) {
+ window.domAutomationController.setAutomationId(1);
+ window.domAutomationController.send(cmd);
+ }
+
+ function agreed(form) {
+ form.continue_button.disabled = !form.continue_button.disabled;
+ }
+</script>
+</head>
+<body oncontextmenu="return false;">
+<div class="background"><img src="../security/resources/ssl_roadblock_background.png" width="100%" height="100%" alt="background" /></div>
+<table width="100%" cellspacing="0" cellpadding="0">
+ <td class="cell" valign="middle" align="center">
+ <div class="box">
+ <div class="icon"><img src="phishing_icon.png" alt="Malware Icon" /></div>
+ <div class="title" jscontent="headLine"></div>
+ <div class="main" jseval="this.innerHTML = $this.description1;"></div>
+ <div class="main" jseval="this.innerHTML = $this.description2;"></div>
+ <div class="main"><a href="" jscontent="description3" onclick="sendCommand(2); return false;"></a></div>
+ <div class="main">
+ <form class="submission">
+ <input name="checky" type="checkbox" onclick="agreed(this.form)">&nbsp;<span jscontent="confirm_text"></span>
+ <input type="button" name="continue_button" jsvalues="value:continue_button" disabled="true" onclick="sendCommand(1)"><br>
+ <input type="button" name="back_button" jsvalues="value:back_button" onclick="sendCommand(0)">
+ </form>
+ </div>
+ </div>
+ </td>
+</table>
+</body>
+</html>
diff --git a/chrome/browser/resources/safe_browsing_phishing_block.html b/chrome/browser/resources/safe_browsing_phishing_block.html
new file mode 100644
index 0000000..2731f82
--- /dev/null
+++ b/chrome/browser/resources/safe_browsing_phishing_block.html
@@ -0,0 +1,103 @@
+<html id="template_root" jsvalues="dir:textdirection">
+<head>
+<title jscontent="title"></title>
+<style type="text/css">
+body {
+ background-color:#500;
+ font-family:arial;
+ margin:0px;
+}
+.background {
+ position:absolute;
+ width:100%;
+ height:100%;
+}
+.cell {
+ padding:40px;
+}
+.box {
+ width:80%;
+ background-color:white;
+ color:black;
+ font-size:10pt;
+ line-height:16pt;
+ text-align:left;
+ padding:20px;
+ position:relative;
+ -webkit-box-shadow:3px 3px 8px #200;
+ -webkit-border-radius:5px;
+}
+html[dir='rtl'] .box {
+ text-align:right;
+}
+.icon {
+ position:absolute;
+}
+.title {
+ margin: 0px 87px 0px;
+ font-size:18pt;
+ margin-bottom:6pt;
+ font-weight:bold;
+ color:#660000;
+}
+.main {
+ margin:0px 90px 0px;
+}
+.submission {
+ margin:15px 5px 15px 0px;
+ padding:0px;
+}
+input {
+ margin:0px;
+}
+.proceedbutton {
+}
+.helpbutton {
+ float:right;
+}
+html[dir='rtl'] .helpbutton {
+ float:left;
+}
+.example {
+ margin: 30px 90px 0px;
+ border-top:1px solid #ccc;
+ padding-top:6px;
+}
+.moreinfotitle {
+ margin-left:5px;
+ margin-right:5px;
+}
+</style>
+
+<script>
+ function sendCommand(cmd) {
+ window.domAutomationController.setAutomationId(1);
+ window.domAutomationController.send(cmd);
+ }
+
+ function agreed(form) {
+ form.continue_button.disabled = !form.continue_button.disabled;
+ }
+</script>
+</head>
+<body oncontextmenu="return false;">
+<div class="background"><img src="../security/resources/ssl_roadblock_background.png" width="100%" height="100%" alt="background" /></div>
+<table width="100%" cellspacing="0" cellpadding="0">
+ <td class="cell" valign="middle" align="center">
+ <div class="box">
+ <div class="icon"><img src="phishing_icon.png" alt="Phishing Warning Icon" /></div>
+ <div class="title" jscontent="headLine"></div>
+ <div class="main" jseval="this.innerHTML = $this.description1;"></div>
+ <div class="main"><a href="" jscontent="description2" onclick="sendCommand(2); return false;"></a></div>
+ <div class="main">
+ <form class="submission">
+ <input type="button" name="continue_button" jsvalues="value:continue_button" onclick="sendCommand(1)">
+ <input type="button" name="back_button" jsvalues="value:back_button" onclick="sendCommand(0)">
+ </form>
+ </div>
+ <div class="main"><a href="" onclick="sendCommand(3); return false;" jscontent="report_error"></a></div>
+ </div>
+ </td>
+</table>
+</body>
+</html>
diff --git a/chrome/browser/resources/ssl_error.html b/chrome/browser/resources/ssl_error.html
new file mode 100644
index 0000000..fe6414a
--- /dev/null
+++ b/chrome/browser/resources/ssl_error.html
@@ -0,0 +1,22 @@
+<html id="template_root">
+
+<head>
+ <title jscontent="title"></title>
+ <script>
+ function sendCommand(cmd) {
+ window.domAutomationController.setAutomationId(1);
+ window.domAutomationController.send(cmd);
+ }
+ </script>
+</head>
+
+<body>
+ <h1 jscontent="headLine"></h1>
+ <div jscontent="description"></div>
+ <form a="">
+ <input type="button" jsvalues="value:proceed" onClick="sendCommand(1);"/>
+ <input type="button" jsvalues="value:leave" onClick="sendCommand(0);"/>
+ </form>
+
+</body>
+</html>