blob: d0f10f5623f030543d95db4e08d199290a227e97 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// If you set this variable to true, then compile and run Chrome, all messages
// sent with chrome.send() will be intercepted and their callback data will be
// recorded. You can later see the recorded data by executing chrome.mock()
// on Web Developer Tools' console.
var recordMockData = false;
(recordMockData || !/^chrome:\/\/./.test(location.href)) && (function() {
var __chrome__ = chrome;
var shouldRegisterData = !!window.chrome && !!window.chrome.send;
var NO_CALLBACK = 1;
// Only messages registered in the callback map will be intercepted.
var callbackMap = {
'blacklistURLFromMostVisited': NO_CALLBACK,
'clearMostVisitedURLsBlacklist': NO_CALLBACK,
'getApps': 'ntp.getAppsCallback',
'getForeignSessions': 'ntp.setForeignSessions',
'getMostVisited': 'ntp.setMostVisitedPages',
'getRecentlyClosedTabs': 'ntp.setRecentlyClosedTabs',
'metricsHandler:logEventTime': NO_CALLBACK,
'metricsHandler:recordInHistogram': NO_CALLBACK,
'removeURLsFromMostVisitedBlacklist': NO_CALLBACK,
};
// TODO(pedrosimonetti): include automatically in the recorded data
// TODO(pedrosimonetti): document the special char replacement
var mockedThumbnailUrls = [
'http---www.wikipedia.org-',
'http---www.deviantart.com-',
'http---wefunkradio.com-',
'http---youtube.com-',
'http---amazon.com-',
'http---nytimes.com-',
'http---news.ycombinator.com-',
'http---cnn.com-',
'http---ebay.com-',
'http---www.google.com-chrome-intl-en-welcome.html',
'https---chrome.google.com-webstore-hl-en',
];
//----------------------------------------------------------------------------
// Internals
//----------------------------------------------------------------------------
var dataMap = {};
var recordedDataMap = {};
var isInitialized = false;
function initialize() {
if (shouldRegisterData || !namespace('ntp'))
return;
isInitialized = true;
namespace('ntp.getThumbnailUrl', mockGetThumbnailUrl);
var data = loadTimeData.data_;
document.documentElement.dir = data.textdirection;
document.body.style.fontSize = data.fontsize;
}
function namespace(str, data) {
var ns = str.split('.'), name, object = window;
for (var i = 0, l = ns.length; i < l; i++) {
name = ns[i];
if (data && i == (l - 1))
object = object[name] = data;
else
object = object[name];
}
return object == window ? null : object;
}
function copyArray(arr) {
return Array.prototype.slice.call(arr, 0);
}
function interceptCallback(message, callbackNamespace) {
var original = namespace(callbackNamespace);
namespace(callbackNamespace, function() {
recordedDataMap[message] = copyArray(arguments);
var result = original.apply(window, arguments);
namespace(callbackNamespace, original);
return result;
});
}
function dispatchCallbackForMessage(message) {
var callbackNamespace = callbackMap[message];
var callback = namespace(callbackNamespace);
var data = filterMap[message](dataMap[message]);
callback.apply(window, data);
}
function interceptLoadData() {
window.addEventListener('load', function() {
recordedDataMap['__loadTimeData__'] = loadTimeData.data_;
});
}
function mockGetThumbnailUrl(url) {
url = url.replace(/[:\/\?=]/g, '-');
var mockUrl;
var index = mockedThumbnailUrls.indexOf(url);
if (index != -1)
mockUrl = mockedThumbnailUrls[index];
else
mockUrl = 'non-existent-file-name';
mockUrl = 'mock/images/' + mockUrl + '.jpg';
return mockUrl;
}
function mockLoadData() {
if (loadTimeData)
loadTimeData.data = dataMap['__loadTimeData__'];
}
//----------------------------------------------------------------------------
// ChromeMock implementation
//----------------------------------------------------------------------------
var ChromeMock = {
mock: function(newDataMap) {
if (newDataMap) {
dataMap = newDataMap;
if (!shouldRegisterData)
mockLoadData();
} else {
return recordedDataMap;
}
},
send: function() {
if (!isInitialized)
initialize();
var message = arguments[0];
var shouldCallChromeSend = false;
if (callbackMap.hasOwnProperty(message)) {
var callbackNamespace = callbackMap[message];
if (shouldRegisterData) {
if (callbackNamespace !== NO_CALLBACK)
interceptCallback(message, callbackNamespace);
} else {
if (dataMap.hasOwnProperty(message)) {
var data = dataMap[message];
var callback = namespace(callbackNamespace);
if (filterMap.hasOwnProperty(message))
data = filterMap[message](data);
setTimeout(function() {
callback.apply(window, data);
}, 0);
} else {
if (callbackNamespace !== NO_CALLBACK)
console.warn('No mock registered for message "%s".', message);
else if (serverCallbackMap.hasOwnProperty(message))
serverCallbackMap[message](arguments[1]);
}
}
} else {
shouldCallChromeSend = true;
console.warn('No callback data registered for message "%s".', message);
}
shouldCallChromeSend = shouldCallChromeSend || shouldRegisterData;
if (shouldCallChromeSend) {
if (__chrome__ && __chrome__.send)
__chrome__.send(message);
}
},
};
//----------------------------------------------------------------------------
// C++ mock implementation
//----------------------------------------------------------------------------
var mostVisitedBlackList = {};
var filterMap = {
getMostVisited: function(data) {
var filtered = [];
var list = data[0];
var hasBlacklistedUrls = false;
for (var i = 0, length = list.length; i < length; i++) {
if (mostVisitedBlackList.hasOwnProperty('' + i))
hasBlacklistedUrls = true;
else
filtered.push(list[i]);
}
return [filtered, hasBlacklistedUrls];
}
};
var serverCallbackMap = {
blacklistURLFromMostVisited: function(urls) {
var url = urls[0];
var data = dataMap['getMostVisited'][0];
for (var i = 0, length = data.length; i < length; i++) {
if (data[i].url == url)
mostVisitedBlackList['' + i] = 1;
}
},
removeURLsFromMostVisitedBlacklist: function(urls) {
var url = urls[0];
var data = dataMap['getMostVisited'][0];
for (var i = 0, length = data.length; i < length; i++) {
if (data[i].url == url)
delete mostVisitedBlackList['' + i];
}
dispatchCallbackForMessage('getMostVisited');
},
clearMostVisitedURLsBlacklist: function() {
mostVisitedBlackList = {};
dispatchCallbackForMessage('getMostVisited');
},
};
//----------------------------------------------------------------------------
// Debug
//----------------------------------------------------------------------------
var debugArgs = {
debug: false,
slownessFactor: null
};
var debugStylesheet = null;
var animationSelectorSpeedMap = {
'#card-slider-frame': 250,
'.dot': 200,
'.animate-page-height': 200,
'.animate-grid-width': 200,
'.tile-grid-content': 200,
'.tile-row': 200,
'.animate-grid-width .tile-cell': 200,
};
function adjustAnimationSpeed(slownessFactor) {
slownessFactor = slownessFactor || 1;
var animationRules = [];
for (var selector in animationSelectorSpeedMap) {
if (animationSelectorSpeedMap.hasOwnProperty(selector)) {
animationRules.push(selector + ' { -webkit-transition-duration: ' +
Math.round(animationSelectorSpeedMap[selector] * slownessFactor) +
'ms !important; }\n');
}
}
var doc = document;
debugStylesheet = doc.getElementById('debugStylesheet');
if (debugStylesheet)
debugStylesheet.parentElement.removeChild(debugStylesheet);
debugStylesheet = doc.createElement('style');
debugStylesheet.id = 'debugStylesheet';
debugStylesheet.textContent = animationRules.join('');
doc.querySelector('head').appendChild(debugStylesheet);
}
function getArgs() {
var url = location.href;
var parts = url.split('?');
var args = parts[1];
if (args) {
var pairs = args.split('&');
for (var i = 0, l = pairs.length; i < l; i++) {
var pair = pairs[i];
var data = pair.split('=');
var key = data[0];
var value = data[1];
debugArgs[key] = typeof value == 'undefined' ? true :
parseInt(value) ? parseInt(value) : value;
}
}
}
window.addEventListener('load', function() {
getArgs();
if (debugArgs.debug)
document.body.classList.add('debug');
var slownessFactor = parseInt(debugArgs.slownessFactor);
if (slownessFactor)
adjustAnimationSpeed(slownessFactor);
});
//----------------------------------------------------------------------------
// ChromeMock initialization
//----------------------------------------------------------------------------
if (shouldRegisterData)
interceptLoadData();
window.chrome = ChromeMock;
})();