Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1012)

Side by Side Diff: chrome/browser/resources/inspect/inspect.js

Issue 65143004: DevTools: Refactor InspectUI class for extensibility (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 var MIN_VERSION_TAB_CLOSE = 25; 5 var MIN_VERSION_TAB_CLOSE = 25;
6 var MIN_VERSION_TARGET_ID = 26; 6 var MIN_VERSION_TARGET_ID = 26;
7 var MIN_VERSION_NEW_TAB = 29; 7 var MIN_VERSION_NEW_TAB = 29;
8 var MIN_VERSION_TAB_ACTIVATE = 30; 8 var MIN_VERSION_TAB_ACTIVATE = 30;
9 9
10 function inspect(data) { 10 function sendCommand(command, args) {
11 chrome.send('inspect', [data]); 11 chrome.send(command, Array.prototype.slice.call(arguments, 1));
12 } 12 }
13 13
14 function activate(data) { 14 function sendTargetCommand(command, target) {
15 chrome.send('activate', [data]); 15 sendCommand(command, target.source, target.id);
16 }
17
18 function close(data) {
19 chrome.send('close', [data]);
20 }
21
22 function reload(data) {
23 chrome.send('reload', [data]);
24 }
25
26 function open(browserId, url) {
27 chrome.send('open', [browserId, url]);
28 }
29
30 function launch(packageId) {
31 chrome.send('launch', [packageId]);
32 } 16 }
33 17
34 function removeChildren(element_id) { 18 function removeChildren(element_id) {
35 var element = $(element_id); 19 var element = $(element_id);
36 element.textContent = ''; 20 element.textContent = '';
37 } 21 }
38 22
39 function onload() { 23 function onload() {
40 var tabContents = document.querySelectorAll('#content > div'); 24 var tabContents = document.querySelectorAll('#content > div');
41 for (var i = 0; i != tabContents.length; i++) { 25 for (var i = 0; i != tabContents.length; i++) {
42 var tabContent = tabContents[i]; 26 var tabContent = tabContents[i];
43 var tabName = tabContent.querySelector('.content-header').textContent; 27 var tabName = tabContent.querySelector('.content-header').textContent;
44 28
45 var tabHeader = document.createElement('div'); 29 var tabHeader = document.createElement('div');
46 tabHeader.className = 'tab-header'; 30 tabHeader.className = 'tab-header';
47 var button = document.createElement('button'); 31 var button = document.createElement('button');
48 button.textContent = tabName; 32 button.textContent = tabName;
49 tabHeader.appendChild(button); 33 tabHeader.appendChild(button);
50 tabHeader.addEventListener('click', selectTab.bind(null, tabContent.id)); 34 tabHeader.addEventListener('click', selectTab.bind(null, tabContent.id));
51 $('navigation').appendChild(tabHeader); 35 $('navigation').appendChild(tabHeader);
52 } 36 }
53 var selectedTabName = window.location.hash.slice(1) || 'devices'; 37 var selectedTabName = window.location.hash.slice(1) || 'devices';
54 selectTab(selectedTabName); 38 selectTab(selectedTabName);
55 initSettings(); 39 initSettings();
56 chrome.send('init-ui'); 40 sendCommand('init-ui');
57 } 41 }
58 42
59 function selectTab(id) { 43 function selectTab(id) {
60 var tabContents = document.querySelectorAll('#content > div'); 44 var tabContents = document.querySelectorAll('#content > div');
61 var tabHeaders = $('navigation').querySelectorAll('.tab-header'); 45 var tabHeaders = $('navigation').querySelectorAll('.tab-header');
62 for (var i = 0; i != tabContents.length; i++) { 46 for (var i = 0; i != tabContents.length; i++) {
63 var tabContent = tabContents[i]; 47 var tabContent = tabContents[i];
64 var tabHeader = tabHeaders[i]; 48 var tabHeader = tabHeaders[i];
65 if (tabContent.id == id) { 49 if (tabContent.id == id) {
66 tabContent.classList.add('selected'); 50 tabContent.classList.add('selected');
67 tabHeader.classList.add('selected'); 51 tabHeader.classList.add('selected');
68 } else { 52 } else {
69 tabContent.classList.remove('selected'); 53 tabContent.classList.remove('selected');
70 tabHeader.classList.remove('selected'); 54 tabHeader.classList.remove('selected');
71 } 55 }
72 } 56 }
73 window.location.hash = id; 57 window.location.hash = id;
74 } 58 }
75 59
60 function populateTargets(source, data) {
61 if (source == 'renderers')
62 populateWebContentsTargets(data);
63 else if (source == 'workers')
64 populateWorkerTargets(data);
65 else if (source == 'adb')
66 populateRemoteTargets(data);
67 else
68 console.error('Unknown source type: ' + source);
69 }
70
76 function populateWebContentsTargets(data) { 71 function populateWebContentsTargets(data) {
77 removeChildren('pages-list'); 72 removeChildren('pages-list');
78 removeChildren('extensions-list'); 73 removeChildren('extensions-list');
79 removeChildren('apps-list'); 74 removeChildren('apps-list');
80 removeChildren('others-list'); 75 removeChildren('others-list');
81 76
82 for (var i = 0; i < data.length; i++) { 77 for (var i = 0; i < data.length; i++) {
83 if (data[i].type === 'page') 78 if (data[i].type === 'page')
84 addToPagesList(data[i]); 79 addToPagesList(data[i]);
85 else if (data[i].type === 'background_page') 80 else if (data[i].type === 'background_page')
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 124
130 var deviceList = $('devices-list'); 125 var deviceList = $('devices-list');
131 if (alreadyDisplayed(deviceList, devices)) 126 if (alreadyDisplayed(deviceList, devices))
132 return; 127 return;
133 128
134 function removeObsolete(validIds, section) { 129 function removeObsolete(validIds, section) {
135 if (validIds.indexOf(section.id) < 0) 130 if (validIds.indexOf(section.id) < 0)
136 section.remove(); 131 section.remove();
137 } 132 }
138 133
139 var newDeviceIds = devices.map(function(d) { return d.adbGlobalId }); 134 var newDeviceIds = devices.map(function(d) { return d.id });
140 Array.prototype.forEach.call( 135 Array.prototype.forEach.call(
141 deviceList.querySelectorAll('.device'), 136 deviceList.querySelectorAll('.device'),
142 removeObsolete.bind(null, newDeviceIds)); 137 removeObsolete.bind(null, newDeviceIds));
143 138
144 for (var d = 0; d < devices.length; d++) { 139 for (var d = 0; d < devices.length; d++) {
145 var device = devices[d]; 140 var device = devices[d];
146 141
147 var deviceSection = $(device.adbGlobalId); 142 var deviceSection = $(device.id);
148 if (!deviceSection) { 143 if (!deviceSection) {
149 deviceSection = document.createElement('div'); 144 deviceSection = document.createElement('div');
150 deviceSection.id = device.adbGlobalId; 145 deviceSection.id = device.id;
151 deviceSection.className = 'device'; 146 deviceSection.className = 'device';
152 deviceList.appendChild(deviceSection); 147 deviceList.appendChild(deviceSection);
153 148
154 var deviceHeader = document.createElement('div'); 149 var deviceHeader = document.createElement('div');
155 deviceHeader.className = 'device-header'; 150 deviceHeader.className = 'device-header';
156 deviceSection.appendChild(deviceHeader); 151 deviceSection.appendChild(deviceHeader);
157 152
158 var deviceName = document.createElement('div'); 153 var deviceName = document.createElement('div');
159 deviceName.className = 'device-name'; 154 deviceName.className = 'device-name';
160 deviceHeader.appendChild(deviceName); 155 deviceHeader.appendChild(deviceName);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 portNumber.className = 'port-number'; 205 portNumber.className = 'port-number';
211 portNumber.textContent = ':' + port; 206 portNumber.textContent = ':' + port;
212 if (status > 0) 207 if (status > 0)
213 portNumber.textContent += '(' + status + ')'; 208 portNumber.textContent += '(' + status + ')';
214 devicePorts.appendChild(portNumber); 209 devicePorts.appendChild(portNumber);
215 } 210 }
216 } 211 }
217 212
218 var browserList = deviceSection.querySelector('.browsers'); 213 var browserList = deviceSection.querySelector('.browsers');
219 var newBrowserIds = 214 var newBrowserIds =
220 device.browsers.map(function(b) { return b.adbGlobalId }); 215 device.browsers.map(function(b) { return b.id });
221 Array.prototype.forEach.call( 216 Array.prototype.forEach.call(
222 browserList.querySelectorAll('.browser'), 217 browserList.querySelectorAll('.browser'),
223 removeObsolete.bind(null, newBrowserIds)); 218 removeObsolete.bind(null, newBrowserIds));
224 219
225 for (var b = 0; b < device.browsers.length; b++) { 220 for (var b = 0; b < device.browsers.length; b++) {
226 var browser = device.browsers[b]; 221 var browser = device.browsers[b];
227 222
228 var majorChromeVersion = browser.adbBrowserChromeVersion; 223 var majorChromeVersion = browser.adbBrowserChromeVersion;
229 224
230 var pageList; 225 var pageList;
231 var browserSection = $(browser.adbGlobalId); 226 var browserSection = $(browser.id);
232 if (browserSection) { 227 if (browserSection) {
233 pageList = browserSection.querySelector('.pages'); 228 pageList = browserSection.querySelector('.pages');
234 } else { 229 } else {
235 browserSection = document.createElement('div'); 230 browserSection = document.createElement('div');
236 browserSection.id = browser.adbGlobalId; 231 browserSection.id = browser.id;
237 browserSection.className = 'browser'; 232 browserSection.className = 'browser';
238 insertChildSortedById(browserList, browserSection); 233 insertChildSortedById(browserList, browserSection);
239 234
240 var browserHeader = document.createElement('div'); 235 var browserHeader = document.createElement('div');
241 browserHeader.className = 'browser-header'; 236 browserHeader.className = 'browser-header';
242 237
243 var browserName = document.createElement('div'); 238 var browserName = document.createElement('div');
244 browserName.className = 'browser-name'; 239 browserName.className = 'browser-name';
245 browserHeader.appendChild(browserName); 240 browserHeader.appendChild(browserName);
246 browserName.textContent = browser.adbBrowserName; 241 browserName.textContent = browser.adbBrowserName;
247 if (browser.adbBrowserVersion) 242 if (browser.adbBrowserVersion)
248 browserName.textContent += ' (' + browser.adbBrowserVersion + ')'; 243 browserName.textContent += ' (' + browser.adbBrowserVersion + ')';
249 browserSection.appendChild(browserHeader); 244 browserSection.appendChild(browserHeader);
250 245
251 if (majorChromeVersion >= MIN_VERSION_NEW_TAB) { 246 if (majorChromeVersion >= MIN_VERSION_NEW_TAB) {
252 var newPage = document.createElement('div'); 247 var newPage = document.createElement('div');
253 newPage.className = 'open'; 248 newPage.className = 'open';
254 249
255 var newPageUrl = document.createElement('input'); 250 var newPageUrl = document.createElement('input');
256 newPageUrl.type = 'text'; 251 newPageUrl.type = 'text';
257 newPageUrl.placeholder = 'Open tab with url'; 252 newPageUrl.placeholder = 'Open tab with url';
258 newPage.appendChild(newPageUrl); 253 newPage.appendChild(newPageUrl);
259 254
260 var openHandler = function(browserId, input) { 255 var openHandler = function(sourceId, browserId, input) {
261 open(browserId, input.value || 'about:blank'); 256 sendCommand(
vsevik 2013/11/12 14:24:07 I would use sendTargetCommand(browser, url) instea
Vladislav Kaznacheev 2013/11/13 16:02:33 sendTargetCommand accepts 3 args (command, source
257 'open', sourceId, browserId, input.value || 'about:blank');
262 input.value = ''; 258 input.value = '';
263 }.bind(null, browser.adbGlobalId, newPageUrl); 259 }.bind(null, browser.source, browser.id, newPageUrl);
264 newPageUrl.addEventListener('keyup', function(handler, event) { 260 newPageUrl.addEventListener('keyup', function(handler, event) {
265 if (event.keyIdentifier == 'Enter' && event.target.value) 261 if (event.keyIdentifier == 'Enter' && event.target.value)
266 handler(); 262 handler();
267 }.bind(null, openHandler), true); 263 }.bind(null, openHandler), true);
268 264
269 var newPageButton = document.createElement('button'); 265 var newPageButton = document.createElement('button');
270 newPageButton.textContent = 'Open'; 266 newPageButton.textContent = 'Open';
271 newPage.appendChild(newPageButton); 267 newPage.appendChild(newPageButton);
272 newPageButton.addEventListener('click', openHandler, true); 268 newPageButton.addEventListener('click', openHandler, true);
273 269
(...skipping 13 matching lines...) Expand all
287 var page = browser.pages[p]; 283 var page = browser.pages[p];
288 // Attached targets have no unique id until Chrome 26. For such targets 284 // Attached targets have no unique id until Chrome 26. For such targets
289 // it is impossible to activate existing DevTools window. 285 // it is impossible to activate existing DevTools window.
290 page.hasNoUniqueId = page.attached && 286 page.hasNoUniqueId = page.attached &&
291 (majorChromeVersion && majorChromeVersion < MIN_VERSION_TARGET_ID); 287 (majorChromeVersion && majorChromeVersion < MIN_VERSION_TARGET_ID);
292 var row = addTargetToList(page, pageList, ['name', 'url']); 288 var row = addTargetToList(page, pageList, ['name', 'url']);
293 if (page['description']) 289 if (page['description'])
294 addWebViewDetails(row, page); 290 addWebViewDetails(row, page);
295 else 291 else
296 addFavicon(row, page); 292 addFavicon(row, page);
297 if (majorChromeVersion >= MIN_VERSION_TAB_ACTIVATE) 293 if (majorChromeVersion >= MIN_VERSION_TAB_ACTIVATE) {
298 addActionLink(row, 'focus tab', activate.bind(null, page), false); 294 addActionLink(row, 'focus tab',
299 if (majorChromeVersion) 295 sendTargetCommand.bind(null, 'activate', page), false);
300 addActionLink(row, 'reload', reload.bind(null, page), page.attached); 296 }
301 if (majorChromeVersion >= MIN_VERSION_TAB_CLOSE) 297 if (majorChromeVersion) {
302 addActionLink(row, 'close', close.bind(null, page), page.attached); 298 addActionLink(row, 'reload',
299 sendTargetCommand.bind(null, 'reload', page), page.attached);
300 }
301 if (majorChromeVersion >= MIN_VERSION_TAB_CLOSE) {
302 addActionLink(row, 'close',
303 sendTargetCommand.bind(null, 'close', page), page.attached);
304 }
303 } 305 }
304 } 306 }
305 307
306 var packageList = deviceSection.querySelector('.packages'); 308 var packageList = deviceSection.querySelector('.packages');
307 packageList.textContent = ''; 309 packageList.textContent = '';
308 310
309 if (device.packages.length) { 311 if (device.packages.length) {
310 var packagesHeader = document.createElement('div'); 312 var packagesHeader = document.createElement('div');
311 packagesHeader.className = 'packages-header'; 313 packagesHeader.className = 'packages-header';
312 packagesHeader.textContent = 314 packagesHeader.textContent =
313 device.browsers.length ? 'Also installed:' : 'Installed browsers:'; 315 device.browsers.length ? 'Also installed:' : 'Installed browsers:';
314 packageList.appendChild(packagesHeader); 316 packageList.appendChild(packagesHeader);
315 } 317 }
316 318
317 for (var p = 0; p < device.packages.length; p++) { 319 for (var p = 0; p < device.packages.length; p++) {
318 var packageSection = document.createElement('div'); 320 var packageSection = document.createElement('div');
319 packageSection.className = 'package'; 321 packageSection.className = 'package';
320 packageList.appendChild(packageSection); 322 packageList.appendChild(packageSection);
321 323
322 var launchButton = document.createElement('button'); 324 var launchButton = document.createElement('button');
323 launchButton.textContent = 'Launch'; 325 launchButton.textContent = 'Launch';
324 launchButton.addEventListener( 326 launchButton.addEventListener(
325 'click', launch.bind(null, device.packages[p].adbGlobalId), true); 327 'click',
328 sendTargetCommand.bind(null, 'launch', device.packages[p]),
329 true);
326 packageSection.appendChild(launchButton); 330 packageSection.appendChild(launchButton);
327 331
328 var packageDisplayName = document.createElement('span'); 332 var packageDisplayName = document.createElement('span');
329 packageDisplayName.textContent = device.packages[p].adbBrowserName; 333 packageDisplayName.textContent = device.packages[p].adbBrowserName;
330 packageSection.appendChild(packageDisplayName); 334 packageSection.appendChild(packageDisplayName);
331 } 335 }
332 } 336 }
333 } 337 }
334 338
335 function addToPagesList(data) { 339 function addToPagesList(data) {
(...skipping 14 matching lines...) Expand all
350 var guestRow = addTargetToList(guest, row, ['name', 'url']); 354 var guestRow = addTargetToList(guest, row, ['name', 'url']);
351 guestRow.classList.add('guest'); 355 guestRow.classList.add('guest');
352 addFavicon(guestRow, guest); 356 addFavicon(guestRow, guest);
353 }); 357 });
354 } 358 }
355 } 359 }
356 360
357 function addToWorkersList(data) { 361 function addToWorkersList(data) {
358 var row = 362 var row =
359 addTargetToList(data, $('workers-list'), ['name', 'description', 'url']); 363 addTargetToList(data, $('workers-list'), ['name', 'description', 'url']);
360 addActionLink(row, 'terminate', close.bind(null, data), data.attached); 364 addActionLink(row, 'terminate',
365 sendTargetCommand.bind(null, 'close', data), data.attached);
361 } 366 }
362 367
363 function addToOthersList(data) { 368 function addToOthersList(data) {
364 addTargetToList(data, $('others-list'), ['url']); 369 addTargetToList(data, $('others-list'), ['url']);
365 } 370 }
366 371
367 function formatValue(data, property) { 372 function formatValue(data, property) {
368 var value = data[property]; 373 var value = data[property];
369 374
370 if (property == 'name' && value == '') { 375 if (property == 'name' && value == '') {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 for (var j = 0; j < properties.length; j++) 500 for (var j = 0; j < properties.length; j++)
496 subrow.appendChild(formatValue(data, properties[j])); 501 subrow.appendChild(formatValue(data, properties[j]));
497 502
498 if (description) 503 if (description)
499 addWebViewDescription(description, subrowBox); 504 addWebViewDescription(description, subrowBox);
500 505
501 var actionBox = document.createElement('div'); 506 var actionBox = document.createElement('div');
502 actionBox.className = 'actions'; 507 actionBox.className = 'actions';
503 subrowBox.appendChild(actionBox); 508 subrowBox.appendChild(actionBox);
504 509
505 addActionLink(row, 'inspect', inspect.bind(null, data), 510 addActionLink(row, 'inspect', sendTargetCommand.bind(null, 'inspect', data),
506 data.hasNoUniqueId || data.adbAttachedForeign); 511 data.hasNoUniqueId || data.adbAttachedForeign);
507 512
508 list.appendChild(row); 513 list.appendChild(row);
509 return row; 514 return row;
510 } 515 }
511 516
512 function addActionLink(row, text, handler, opt_disabled) { 517 function addActionLink(row, text, handler, opt_disabled) {
513 var link = document.createElement('a'); 518 var link = document.createElement('a');
514 if (opt_disabled) 519 if (opt_disabled)
515 link.classList.add('disabled'); 520 link.classList.add('disabled');
(...skipping 14 matching lines...) Expand all
530 $('port-forwarding-enable').addEventListener('change', enablePortForwarding); 535 $('port-forwarding-enable').addEventListener('change', enablePortForwarding);
531 $('port-forwarding-config-open').addEventListener( 536 $('port-forwarding-config-open').addEventListener(
532 'click', openPortForwardingConfig); 537 'click', openPortForwardingConfig);
533 $('port-forwarding-config-close').addEventListener( 538 $('port-forwarding-config-close').addEventListener(
534 'click', closePortForwardingConfig); 539 'click', closePortForwardingConfig);
535 $('port-forwarding-config-done').addEventListener( 540 $('port-forwarding-config-done').addEventListener(
536 'click', commitPortForwardingConfig.bind(true)); 541 'click', commitPortForwardingConfig.bind(true));
537 } 542 }
538 543
539 function enableDiscoverUsbDevices(event) { 544 function enableDiscoverUsbDevices(event) {
540 chrome.send('set-discover-usb-devices-enabled', [event.target.checked]); 545 sendCommand('set-discover-usb-devices-enabled', event.target.checked);
541 } 546 }
542 547
543 function enablePortForwarding(event) { 548 function enablePortForwarding(event) {
544 chrome.send('set-port-forwarding-enabled', [event.target.checked]); 549 sendCommand('set-port-forwarding-enabled', event.target.checked);
545 } 550 }
546 551
547 function handleKey(event) { 552 function handleKey(event) {
548 switch (event.keyCode) { 553 switch (event.keyCode) {
549 case 13: // Enter 554 case 13: // Enter
550 if (event.target.nodeName == 'INPUT') { 555 if (event.target.nodeName == 'INPUT') {
551 var line = event.target.parentNode; 556 var line = event.target.parentNode;
552 if (!line.classList.contains('fresh') || 557 if (!line.classList.contains('fresh') ||
553 line.classList.contains('empty')) { 558 line.classList.contains('empty')) {
554 commitPortForwardingConfig(true); 559 commitPortForwardingConfig(true);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 portInput.lastValidValue : 650 portInput.lastValidValue :
646 portInput.value; 651 portInput.value;
647 652
648 var location = locationInput.classList.contains('invalid') ? 653 var location = locationInput.classList.contains('invalid') ?
649 locationInput.lastValidValue : 654 locationInput.lastValidValue :
650 locationInput.value; 655 locationInput.value;
651 656
652 if (port && location) 657 if (port && location)
653 config[port] = location; 658 config[port] = location;
654 } 659 }
655 chrome.send('set-port-forwarding-config', [config]); 660 sendCommand('set-port-forwarding-config', config);
656 } 661 }
657 662
658 function updateDiscoverUsbDevicesEnabled(enabled) { 663 function updateDiscoverUsbDevicesEnabled(enabled) {
659 var checkbox = $('discover-usb-devices-enable'); 664 var checkbox = $('discover-usb-devices-enable');
660 checkbox.checked = !!enabled; 665 checkbox.checked = !!enabled;
661 checkbox.disabled = false; 666 checkbox.disabled = false;
662 } 667 }
663 668
664 function updatePortForwardingEnabled(enabled) { 669 function updatePortForwardingEnabled(enabled) {
665 var checkbox = $('port-forwarding-enable'); 670 var checkbox = $('port-forwarding-enable');
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 if (line.querySelector('.invalid')) 811 if (line.querySelector('.invalid'))
807 return; 812 return;
808 line.classList.remove('fresh'); 813 line.classList.remove('fresh');
809 var freshLine = createEmptyConfigLine(); 814 var freshLine = createEmptyConfigLine();
810 line.parentNode.appendChild(freshLine); 815 line.parentNode.appendChild(freshLine);
811 if (opt_selectNew) 816 if (opt_selectNew)
812 freshLine.querySelector('.port').focus(); 817 freshLine.querySelector('.port').focus();
813 } 818 }
814 819
815 document.addEventListener('DOMContentLoaded', onload); 820 document.addEventListener('DOMContentLoaded', onload);
821
822 if (window.WebInspector) {
Vladislav Kaznacheev 2013/11/12 11:49:51 Please disregard, this crept in from another patch
vsevik 2013/11/12 14:24:07 Why is this needed?
Vladislav Kaznacheev 2013/11/13 16:02:33 Done.
823 console.log('Loaded into WebInspector');
824 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698