9 V^ W^ X^" Y^C Z^Z [^n \^F ]^щ ^^ _^ `^ a^ b^ c^f d^ e^* f^H g^ h^|
i^ j^# k^>- l^Q m^-U n^`^ t^ r u^ v^ș w^ x^+ y^g! z^3 {^O; lkw mk} nkV ok pk qkw rk sk u u u& ug u uYi uq ur u uC uY u_K ui uk uz u?} u u u, uE uf uj u( u u:
u u& u) u/+ u\4 uP; uXE vDH vW vp vى v% v v v vdz v
v v v
v v v v) v3 v? v[Y vmm v$ v v v vR v7 v v> v@ vG vlW vd vs v6{ vχ v vF v} v v v vV v v$2 v2 v7 vn v vS v% v; v v v v! v/ vH8 vT vU vZ ^$
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('appcache', function() {
'use strict';
var VIEW_DETAILS_TEXT = 'View Details';
var HIDE_DETAILS_TEXT = 'Hide Details';
var GET_ALL_APPCACHE = 'getAllAppCache';
var DELETE_APPCACHE = 'deleteAppCache';
var GET_APPCACHE_DETAILS = 'getAppCacheDetails';
var GET_FILE_DETAILS = 'getFileDetails';
var manifestsToView = [];
var manifestsToDelete = [];
var fileDetailsRequests = [];
function Manifest(url, path, link) {
this.url = url;
this.path = path;
this.link = link;
}
function FileRequest(fileURL, manifestURL, path, groupId, responseId) {
this.fileURL = fileURL;
this.partitionPath = path;
this.manifestURL = manifestURL;
this.groupId = groupId;
this.responseId = responseId;
}
function getFirstAncestor(node, selector) {
while(node) {
if (selector(node)) {
break;
}
node = node.parentNode;
}
return node;
}
function getItemByProperties(list, properties, values) {
return list.find(function(candidate) {
return properties.every(function(key, i) {
return candidate[key] == values[i];
});
}) || null;
}
function removeFromList(list, item, properties) {
var pos = 0;
while (pos < list.length) {
var candidate = list[pos];
if (properties.every(function(key) {
return candidate[key] == item[key];
})) {
list.splice(pos, 1);
} else {
pos++;
}
}
}
function initialize() {
chrome.send(GET_ALL_APPCACHE);
}
function onAllAppCacheInfoReady(partition_path, data) {
var template = jstGetTemplate('appcache-list-template');
var container = $('appcache-list');
container.appendChild(template);
jstProcess(new JsEvalContext(
{appcache_vector: data, partition_path: partition_path}),
template);
var removeLinks = container.querySelectorAll('a.remove-manifest');
for (var i = 0; i < removeLinks.length; ++i) {
removeLinks[i].onclick = deleteAppCacheInfoEventHandler;
}
var viewLinks = container.querySelectorAll('a.view-details');
for (i = 0; i < viewLinks.length; ++i) {
viewLinks[i].onclick = getAppCacheInfoEventHandler;
}
}
function getAppCacheInfoEventHandler(event) {
var link = event.target;
if (link.text.indexOf(VIEW_DETAILS_TEXT) === -1) {
hideAppCacheInfo(link);
} else {
var manifestURL = getFirstAncestor(link, function(node) {
return !!node.manifestURL;
}).manifestURL;
var partitionPath = getFirstAncestor(link, function(node) {
return !!node.partitionPath;
}).partitionPath;
var manifest = new Manifest(manifestURL, partitionPath, link);
if (getItemByProperties(manifestsToView,
['url', 'path'],
[manifestURL, partitionPath])) {
return;
}
manifestsToView.push(manifest);
chrome.send(GET_APPCACHE_DETAILS, [partitionPath, manifestURL]);
}
}
function hideAppCacheInfo(link) {
getFirstAncestor(link, function(node) {
return node.className === 'appcache-info-item';
}).querySelector('.appcache-details').innerHTML = '';
link.text = VIEW_DETAILS_TEXT;
}
function onAppCacheDetailsReady(manifestURL, partitionPath, details) {
if (!details) {
console.log('Cannot show details for "' + manifestURL + '" on partition '
+ '"' + partitionPath + '".');
return;
}
var manifest = getItemByProperties(
manifestsToView, ['url', 'path'], [manifestURL, partitionPath]);
var link = manifest.link;
removeFromList(manifestsToView, manifest, ['url', 'path']);
var container = getFirstAncestor(link, function(node) {
return node.className === 'appcache-info-item';
}).querySelector('.appcache-details');
var template = jstGetTemplate('appcache-info-template');
container.appendChild(template);
jstProcess(
new JsEvalContext({items: simplifyAppCacheInfo(details)}), template);
var fileLinks =
container.querySelectorAll('a.appcache-info-template-file-url');
for (var i = 0; i < fileLinks.length; ++i) {
fileLinks[i].onclick = getFileContentsEventHandler;
}
link.text = HIDE_DETAILS_TEXT;
}
function simplifyAppCacheInfo(detailsVector) {
var simpleVector = [];
for (var index = 0; index < detailsVector.length; ++index) {
var details = detailsVector[index];
var properties = [];
if (details.isManifest) {
properties.push('Manifest');
}
if (details.isExplicit) {
properties.push('Explicit');
}
if (details.isMaster) {
properties.push('Master');
}
if (details.isForeign) {
properties.push('Foreign');
}
if (details.isIntercept) {
properties.push('Intercept');
}
if (details.isFallback) {
properties.push('Fallback');
}
properties = properties.join(',');
simpleVector.push({
size : details.size,
properties : properties,
fileUrl : details.url,
responseId : details.responseId
});
}
return simpleVector;
}
function deleteAppCacheInfoEventHandler(event) {
var link = event.target;
var manifestURL = getFirstAncestor(link, function(node) {
return !!node.manifestURL;
}).manifestURL;
var partitionPath = getFirstAncestor(link, function(node) {
return !!node.partitionPath;
}).partitionPath;
var manifest = new Manifest(manifestURL, partitionPath, link);
manifestsToDelete.push(manifest);
chrome.send(DELETE_APPCACHE, [partitionPath, manifestURL]);
}
function onAppCacheInfoDeleted(partitionPath, manifestURL, deleted) {
var manifest = getItemByProperties(
manifestsToDelete, ['url', 'path'], [manifestURL, partitionPath]);
if (manifest && deleted) {
var link = manifest.link;
var appcacheItemNode = getFirstAncestor(link, function(node) {
return node.className === 'appcache-info-item';
});
var appcacheNode = getFirstAncestor(link, function(node) {
return node.className === 'appcache-item';
});
appcacheItemNode.parentNode.removeChild(appcacheItemNode);
if (appcacheNode.querySelectorAll('.appcache-info-item').length === 0) {
appcacheNode.parentNode.removeChild(appcacheNode);
}
} else if (!deleted) {
// For some reason, the delete command failed.
console.log('Manifest "' + manifestURL + '" on partition "'
+ partitionPath + ' cannot be accessed.');
}
}
function getFileContentsEventHandler(event) {
var link = event.target;
var partitionPath = getFirstAncestor(link, function(node) {
return !!node.partitionPath;
}).partitionPath;
var manifestURL = getFirstAncestor(link, function(node) {
return !!node.manifestURL;
}).manifestURL;
var groupId = getFirstAncestor(link, function(node) {
return !!node.groupId;
}).groupId;
var responseId = link.responseId;
if (!getItemByProperties(fileDetailsRequests,
['manifestURL', 'groupId', 'responseId'],
[manifestURL, groupId, responseId])) {
var fileRequest = new FileRequest(link.innerText, manifestURL,
partitionPath, groupId, responseId);
fileDetailsRequests.push(fileRequest);
chrome.send(GET_FILE_DETAILS,
[partitionPath, manifestURL, groupId, responseId]);
}
}
function onFileDetailsFailed(response, code) {
var request =
getItemByProperties(
fileDetailsRequests,
['manifestURL', 'groupId', 'responseId'],
[response.manifestURL, response.groupId, response.responseId]);
console.log('Failed to get file information for file "'
+ request.fileURL + '" from partition "'
+ request.partitionPath + '" (net result code:' + code +').');
removeFromList(
fileDetailsRequests,
request,
['manifestURL', 'groupId', 'responseId']);
}
function onFileDetailsReady(response, headers, raw_data) {
var request =
getItemByProperties(
fileDetailsRequests,
['manifestURL', 'groupId', 'responseId'],
[response.manifestURL, response.groupId, response.responseId]);
removeFromList(
fileDetailsRequests,
request,
['manifestURL', 'groupId', 'responseId']);
var doc = window.open().document;
var head = document.createElement('head');
doc.title = 'File Details: '.concat(request.fileURL);
var headersDiv = doc.createElement('div');
headersDiv.innerHTML = headers;
doc.body.appendChild(headersDiv);
var hexDumpDiv = doc.createElement('div');
hexDumpDiv.innerHTML = raw_data;
var linkToManifest = doc.createElement('a');
linkToManifest.style.color = "#3C66DD";
linkToManifest.href = request.fileURL;
linkToManifest.target = '_blank';
linkToManifest.innerHTML = request.fileURL;
doc.body.appendChild(linkToManifest);
doc.body.appendChild(headersDiv);
doc.body.appendChild(hexDumpDiv);
copyStylesFrom(document, doc);
}
function copyStylesFrom(src, dest) {
var styles = src.querySelector('style');
if (dest.getElementsByTagName('style').length < 1) {
dest.head.appendChild(dest.createElement('style'));
}
var destStyle= dest.querySelector('style');
var tmp = '';
for (var i = 0; i < styles.length; ++i) {
tmp += styles[i].innerHTML;
}
destStyle.innerHTML = tmp;
}
return {
initialize: initialize,
onAllAppCacheInfoReady: onAllAppCacheInfoReady,
onAppCacheInfoDeleted: onAppCacheInfoDeleted,
onAppCacheDetailsReady : onAppCacheDetailsReady,
onFileDetailsReady : onFileDetailsReady,
onFileDetailsFailed: onFileDetailsFailed
};
});
document.addEventListener('DOMContentLoaded', appcache.initialize);
/* Copyright 2015 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
.appcache-summary {
background-color: rgb(235, 239, 249);
border-top: 1px solid rgb(156, 194, 239);
margin-bottom: 6px;
margin-top: 12px;
padding: 3px;
font-weight: bold;
}
.appcache-item {
margin-bottom: 15px;
margin-top: 6px;
position: relative;
}
.appcache-url {
color: rgb(85, 102, 221);
display: inline-block;
max-width: 500px;
overflow: hidden;
padding-bottom: 1px;
padding-top: 4px;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.appcache-info-template-table {
table-layout: fixed;
}
.appcache-info-properties {
word-wrap: break-word;
}
.appcache-info-url {
color: rgb(85, 102, 221);
display: inline-block;
}
.appcache-manifest-url {
color: rgb(85, 102, 221);
display: inline-block;
max-width: 500px;
overflow: hidden;
padding-bottom: 1px;
padding-top: 4px;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.appcache-info-item {
margin-bottom: 10px;
margin-top: 6px;
margin-left: 6px;
position: relative;
}
.appcache-manifest-commands a {
-webkit-margin-end: 16px;
color: #777;
}
.appcache-info-template-file-url {
width: 200px;
height:25px;
}
.appcache-info-template-file-url {
color: rgb(60, 102, 221);
}
PNG
IHDR a RIDATx^SA
07;:usKHjtAa%81d/
T8|!姜?S: [ü IENDB`PNG
IHDR D PLTE V tRNS @f cIDATx^I
ѽYJpNBW+Jp T
g, 32 s B}QIVըju}0cicpx3^+o: IENDB`PNG
IHDR J#+ IDATx^10Ec{.T¸Lvqve1kp #"y$\^#3tT
*ath2um!D`(BW'MB#bi@sP
HLT*3shsãm3{}\#:uBn|USgL4ݾM]5ףm IENDB`PNG
IHDR . . IDATxO@p.p'eNZAb71