var MIN_VERSION_NEW_TAB = 29;
var MIN_VERSION_TAB_ACTIVATE = 30;
-function inspect(data) {
- chrome.send('inspect', [data]);
+function sendCommand(command, args) {
+ chrome.send(command, Array.prototype.slice.call(arguments, 1));
}
-function activate(data) {
- chrome.send('activate', [data]);
-}
-
-function close(data) {
- chrome.send('close', [data]);
-}
-
-function reload(data) {
- chrome.send('reload', [data]);
-}
-
-function open(browserId, url) {
- chrome.send('open', [browserId, url]);
+function sendTargetCommand(command, target) {
+ sendCommand(command, target.source, target.id);
}
function removeChildren(element_id) {
tabHeader.addEventListener('click', selectTab.bind(null, tabContent.id));
$('navigation').appendChild(tabHeader);
}
- var selectedTabName = window.location.hash.slice(1) || 'devices';
- selectTab(selectedTabName);
+ onHashChange();
initSettings();
- chrome.send('init-ui');
+ sendCommand('init-ui');
+}
+
+function onHashChange() {
+ var hash = window.location.hash.slice(1).toLowerCase();
+ if (!selectTab(hash))
+ selectTab('devices');
}
+/**
+ * @param {string} id Tab id.
+ * @return {boolean} True if successful.
+ */
function selectTab(id) {
var tabContents = document.querySelectorAll('#content > div');
var tabHeaders = $('navigation').querySelectorAll('.tab-header');
+ var found = false;
for (var i = 0; i != tabContents.length; i++) {
var tabContent = tabContents[i];
var tabHeader = tabHeaders[i];
if (tabContent.id == id) {
tabContent.classList.add('selected');
tabHeader.classList.add('selected');
+ found = true;
} else {
tabContent.classList.remove('selected');
tabHeader.classList.remove('selected');
}
}
+ if (!found)
+ return false;
window.location.hash = id;
+ return true;
+}
+
+function populateTargets(source, data) {
+ if (source == 'renderers')
+ populateWebContentsTargets(data);
+ else if (source == 'workers')
+ populateWorkerTargets(data);
+ else if (source == 'adb')
+ populateRemoteTargets(data);
+ else
+ console.error('Unknown source type: ' + source);
}
function populateWebContentsTargets(data) {
section.remove();
}
- var newDeviceIds = devices.map(function(d) { return d.adbGlobalId });
+ var newDeviceIds = devices.map(function(d) { return d.id });
Array.prototype.forEach.call(
deviceList.querySelectorAll('.device'),
removeObsolete.bind(null, newDeviceIds));
+ $('devices-help').hidden = !!devices.length;
+
for (var d = 0; d < devices.length; d++) {
var device = devices[d];
- var deviceSection = $(device.adbGlobalId);
+ var deviceSection = $(device.id);
if (!deviceSection) {
deviceSection = document.createElement('div');
- deviceSection.id = device.adbGlobalId;
+ deviceSection.id = device.id;
deviceSection.className = 'device';
deviceList.appendChild(deviceSection);
deviceName.className = 'device-name';
deviceHeader.appendChild(deviceName);
- if (device.adbSerial) {
- var deviceSerial = document.createElement('div');
- deviceSerial.className = 'device-serial';
- deviceSerial.textContent = '#' + device.adbSerial.toUpperCase();
- deviceHeader.appendChild(deviceSerial);
- }
+ var deviceSerial = document.createElement('div');
+ deviceSerial.className = 'device-serial';
+ deviceSerial.textContent = '#' + device.adbSerial.toUpperCase();
+ deviceHeader.appendChild(deviceSerial);
var devicePorts = document.createElement('div');
devicePorts.className = 'device-ports';
var browserList = deviceSection.querySelector('.browsers');
var newBrowserIds =
- device.browsers.map(function(b) { return b.adbGlobalId });
+ device.browsers.map(function(b) { return b.id });
Array.prototype.forEach.call(
browserList.querySelectorAll('.browser'),
removeObsolete.bind(null, newBrowserIds));
for (var b = 0; b < device.browsers.length; b++) {
var browser = device.browsers[b];
- var isChrome = browser.adbBrowserProduct &&
- browser.adbBrowserProduct.match(/^Chrome/);
-
- var majorChromeVersion = 0;
- if (isChrome && browser.adbBrowserVersion) {
- var match = browser.adbBrowserVersion.match(/^(\d+)/);
- if (match)
- majorChromeVersion = parseInt(match[1]);
- }
+ var majorChromeVersion = browser.adbBrowserChromeVersion;
+ var incompatibleVersion = browser.hasOwnProperty('compatibleVersion') &&
+ !browser.compatibleVersion;
var pageList;
- var browserSection = $(browser.adbGlobalId);
+ var browserSection = $(browser.id);
if (browserSection) {
pageList = browserSection.querySelector('.pages');
} else {
browserSection = document.createElement('div');
- browserSection.id = browser.adbGlobalId;
+ browserSection.id = browser.id;
browserSection.className = 'browser';
insertChildSortedById(browserList, browserSection);
var browserName = document.createElement('div');
browserName.className = 'browser-name';
browserHeader.appendChild(browserName);
- if (browser.adbBrowserPackage && !isChrome)
- browserName.textContent = browser.adbBrowserPackage;
- else
- browserName.textContent = browser.adbBrowserProduct;
+ browserName.textContent = browser.adbBrowserName;
if (browser.adbBrowserVersion)
browserName.textContent += ' (' + browser.adbBrowserVersion + ')';
browserSection.appendChild(browserHeader);
- if (majorChromeVersion >= MIN_VERSION_NEW_TAB) {
+ if (incompatibleVersion) {
+ var warningSection = document.createElement('div');
+ warningSection.className = 'warning';
+ warningSection.textContent =
+ 'You may need a newer version of desktop Chrome. ' +
+ 'Please try Chrome ' + browser.adbBrowserVersion + ' or later.';
+ browserHeader.appendChild(warningSection);
+ } else if (majorChromeVersion >= MIN_VERSION_NEW_TAB) {
var newPage = document.createElement('div');
newPage.className = 'open';
newPageUrl.placeholder = 'Open tab with url';
newPage.appendChild(newPageUrl);
- var openHandler = function(browserId, input) {
- open(browserId, input.value || 'about:blank');
+ var openHandler = function(sourceId, browserId, input) {
+ sendCommand(
+ 'open', sourceId, browserId, input.value || 'about:blank');
input.value = '';
- }.bind(null, browser.adbGlobalId, newPageUrl);
+ }.bind(null, browser.source, browser.id, newPageUrl);
newPageUrl.addEventListener('keyup', function(handler, event) {
if (event.keyIdentifier == 'Enter' && event.target.value)
handler();
browserSection.appendChild(pageList);
}
- if (alreadyDisplayed(browserSection, browser))
+ if (incompatibleVersion || alreadyDisplayed(browserSection, browser))
continue;
pageList.textContent = '';
// Attached targets have no unique id until Chrome 26. For such targets
// it is impossible to activate existing DevTools window.
page.hasNoUniqueId = page.attached &&
- majorChromeVersion < MIN_VERSION_TARGET_ID;
+ (majorChromeVersion && majorChromeVersion < MIN_VERSION_TARGET_ID);
var row = addTargetToList(page, pageList, ['name', 'url']);
if (page['description'])
addWebViewDetails(row, page);
else
addFavicon(row, page);
- if (isChrome) {
- if (majorChromeVersion >= MIN_VERSION_TAB_ACTIVATE) {
- addActionLink(row, 'focus tab', activate.bind(null, page), false);
- }
- addActionLink(row, 'reload', reload.bind(null, page), page.attached);
- if (majorChromeVersion >= MIN_VERSION_TAB_CLOSE) {
- addActionLink(
- row, 'close', close.bind(null, page), page.attached);
- }
+ if (majorChromeVersion >= MIN_VERSION_TAB_ACTIVATE) {
+ addActionLink(row, 'focus tab',
+ sendTargetCommand.bind(null, 'activate', page), false);
+ }
+ if (majorChromeVersion) {
+ addActionLink(row, 'reload',
+ sendTargetCommand.bind(null, 'reload', page), page.attached);
+ }
+ if (majorChromeVersion >= MIN_VERSION_TAB_CLOSE) {
+ addActionLink(row, 'close',
+ sendTargetCommand.bind(null, 'close', page), page.attached);
}
}
}
function addToPagesList(data) {
var row = addTargetToList(data, $('pages-list'), ['name', 'url']);
addFavicon(row, data);
+ if (data.guests)
+ addGuestViews(row, data.guests);
}
function addToExtensionsList(data) {
var row = addTargetToList(data, $('extensions-list'), ['name', 'url']);
addFavicon(row, data);
+ if (data.guests)
+ addGuestViews(row, data.guests);
}
function addToAppsList(data) {
var row = addTargetToList(data, $('apps-list'), ['name', 'url']);
addFavicon(row, data);
- if (data.guests) {
- Array.prototype.forEach.call(data.guests, function(guest) {
- var guestRow = addTargetToList(guest, row, ['name', 'url']);
- guestRow.classList.add('guest');
- addFavicon(guestRow, guest);
- });
- }
+ if (data.guests)
+ addGuestViews(row, data.guests);
+}
+
+function addGuestViews(row, guests) {
+ Array.prototype.forEach.call(guests, function(guest) {
+ var guestRow = addTargetToList(guest, row, ['name', 'url']);
+ guestRow.classList.add('guest');
+ addFavicon(guestRow, guest);
+ });
}
function addToWorkersList(data) {
var row =
addTargetToList(data, $('workers-list'), ['name', 'description', 'url']);
- addActionLink(row, 'terminate', close.bind(null, data), data.attached);
+ addActionLink(row, 'terminate',
+ sendTargetCommand.bind(null, 'close', data), data.attached);
}
function addToOthersList(data) {
if (text.length > 100)
text = text.substring(0, 100) + '\u2026';
- var span = document.createElement('div');
- span.textContent = text;
- span.className = property;
- return span;
+ var div = document.createElement('div');
+ div.textContent = text;
+ div.className = property;
+ return div;
}
function addFavicon(row, data) {
var favicon = document.createElement('img');
if (data['faviconUrl'])
favicon.src = data['faviconUrl'];
- row.insertBefore(favicon, row.firstChild);
+ var propertiesBox = row.querySelector('.properties-box');
+ propertiesBox.insertBefore(favicon, propertiesBox.firstChild);
}
function addWebViewDetails(row, data) {
subRow.className += ' invisible-view';
if (viewStatus.visibility)
subRow.appendChild(formatValue(viewStatus, 'visibility'));
- subRow.appendChild(formatValue(viewStatus, 'position'));
+ if (viewStatus.position)
+ subRow.appendChild(formatValue(viewStatus, 'position'));
subRow.appendChild(formatValue(viewStatus, 'size'));
- var mainSubrow = row.querySelector('.subrow.main');
- if (mainSubrow.nextSibling)
- mainSubrow.parentNode.insertBefore(subRow, mainSubrow.nextSibling);
- else
- mainSubrow.parentNode.appendChild(subRow);
+ var subrowBox = row.querySelector('.subrow-box');
+ subrowBox.insertBefore(subRow, row.querySelector('.actions'));
}
function addWebViewThumbnail(row, webview, screenWidth, screenHeight) {
screenRect.appendChild(viewRect);
}
- row.insertBefore(thumbnail, row.firstChild);
+ var propertiesBox = row.querySelector('.properties-box');
+ propertiesBox.insertBefore(thumbnail, propertiesBox.firstChild);
}
function addTargetToList(data, list, properties) {
var row = document.createElement('div');
row.className = 'row';
+ var propertiesBox = document.createElement('div');
+ propertiesBox.className = 'properties-box';
+ row.appendChild(propertiesBox);
+
var subrowBox = document.createElement('div');
subrowBox.className = 'subrow-box';
- row.appendChild(subrowBox);
+ propertiesBox.appendChild(subrowBox);
var subrow = document.createElement('div');
- subrow.className = 'subrow main';
+ subrow.className = 'subrow';
subrowBox.appendChild(subrow);
- var description = null;
for (var j = 0; j < properties.length; j++)
subrow.appendChild(formatValue(data, properties[j]));
- if (description)
- addWebViewDescription(description, subrowBox);
-
var actionBox = document.createElement('div');
actionBox.className = 'actions';
subrowBox.appendChild(actionBox);
- addActionLink(row, 'inspect', inspect.bind(null, data),
+ addActionLink(row, 'inspect', sendTargetCommand.bind(null, 'inspect', data),
data.hasNoUniqueId || data.adbAttachedForeign);
list.appendChild(row);
}
function addActionLink(row, text, handler, opt_disabled) {
- var link = document.createElement('a');
+ var link = document.createElement('span');
+ link.classList.add('action');
if (opt_disabled)
link.classList.add('disabled');
else
link.classList.remove('disabled');
- link.setAttribute('href', '#');
link.textContent = text;
link.addEventListener('click', handler, true);
row.querySelector('.actions').appendChild(link);
}
function enableDiscoverUsbDevices(event) {
- chrome.send('set-discover-usb-devices-enabled', [event.target.checked]);
+ sendCommand('set-discover-usb-devices-enabled', event.target.checked);
}
function enablePortForwarding(event) {
- chrome.send('set-port-forwarding-enabled', [event.target.checked]);
+ sendCommand('set-port-forwarding-enabled', event.target.checked);
}
function handleKey(event) {
}
if (window.holdDevices) {
- populateDeviceLists(window.holdDevices);
+ populateRemoteTargets(window.holdDevices);
delete window.holdDevices;
}
if (port && location)
config[port] = location;
}
- chrome.send('set-port-forwarding-config', [config]);
+ sendCommand('set-port-forwarding-config', config);
}
function updateDiscoverUsbDevicesEnabled(enabled) {
line.classList.contains('fresh') &&
!line.classList.contains('empty')) {
// Tabbing forward on the fresh line, try create a new empty one.
- commitFreshLineIfValid(true);
- e.preventDefault();
+ if (commitFreshLineIfValid(true))
+ e.preventDefault();
}
});
if (!match)
return false;
var port = parseInt(match[1]);
- if (port < 5000 || 10000 < port)
+ if (port < 1024 || 65535 < port)
return false;
var inputs = document.querySelectorAll('input.port:not(.invalid)');
}
function validateLocation(input) {
- var match = input.value.match(/^([a-zA-Z0-9\.]+):(\d+)$/);
+ var match = input.value.match(/^([a-zA-Z0-9\.\-_]+):(\d+)$/);
if (!match)
return false;
var port = parseInt(match[2]);
- return port <= 10000;
+ return port <= 65535;
}
function createEmptyConfigLine() {
function commitFreshLineIfValid(opt_selectNew) {
var line = document.querySelector('.port-forwarding-pair.fresh');
if (line.querySelector('.invalid'))
- return;
+ return false;
line.classList.remove('fresh');
var freshLine = createEmptyConfigLine();
line.parentNode.appendChild(freshLine);
if (opt_selectNew)
freshLine.querySelector('.port').focus();
+ return true;
}
document.addEventListener('DOMContentLoaded', onload);
+
+window.addEventListener('hashchange', onHashChange);