diff --git a/extensions/chromium/pdfHandler.js b/extensions/chromium/pdfHandler.js index 38e3b09c1..95f55732a 100644 --- a/extensions/chromium/pdfHandler.js +++ b/extensions/chromium/pdfHandler.js @@ -252,6 +252,32 @@ chrome.extension.isAllowedFileSchemeAccess(function(isAllowedAccess) { }); chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { + if (message && message.action === 'getParentOrigin') { + // getParentOrigin is used to determine whether it is safe to embed a + // sensitive (local) file in a frame. + if (!sender.tab) { + sendResponse(''); + return; + } + // TODO: This should be the URL of the parent frame, not the tab. But + // chrome-extension:-URLs are not visible in the webNavigation API + // (https://crbug.com/326768), so the next best thing is using the tab's URL + // for making security decisions. + var parentUrl = sender.tab.url; + if (!parentUrl) { + sendResponse(''); + return; + } + if (parentUrl.lastIndexOf('file:', 0) === 0) { + sendResponse('file://'); + return; + } + // The regexp should always match for valid URLs, but in case it doesn't, + // just give the full URL (e.g. data URLs). + var origin = /^[^:]+:\/\/[^/]+/.exec(parentUrl); + sendResponse(origin ? origin[1] : parentUrl); + return true; + } if (message && message.action === 'isAllowedFileSchemeAccess') { chrome.extension.isAllowedFileSchemeAccess(sendResponse); return true; diff --git a/web/chromecom.js b/web/chromecom.js index 2b136fc65..8d4014084 100644 --- a/web/chromecom.js +++ b/web/chromecom.js @@ -113,18 +113,25 @@ var ChromeCom = (function ChromeComClosure() { return; } if (/^file?:/.test(file)) { - if (top !== window && !/^file:/i.test(location.ancestorOrigins[0])) { - PDFViewerApplication.error('Blocked ' + location.ancestorOrigins[0] + - ' from loading ' + file + '. Refused to load a local file in a ' + - ' non-local page for security reasons.'); - return; - } - isAllowedFileSchemeAccess(function(isAllowedAccess) { - if (isAllowedAccess) { - PDFViewerApplication.open(file); - } else { - requestAccessToLocalFile(file); + getEmbedderOrigin(function(origin) { + // If the origin cannot be determined, let Chrome decide whether to + // allow embedding files. Otherwise, only allow local files to be + // embedded from local files or Chrome extensions. + // Even without this check, the file load in frames is still blocked, + // but this may change in the future (https://crbug.com/550151). + if (origin && !/^file:|^chrome-extension:/.test(origin)) { + PDFViewerApplication.error('Blocked ' + origin + ' from loading ' + + file + '. Refused to load a local file in a non-local page ' + + 'for security reasons.'); + return; } + isAllowedFileSchemeAccess(function(isAllowedAccess) { + if (isAllowedAccess) { + PDFViewerApplication.open(file); + } else { + requestAccessToLocalFile(file); + } + }); }); return; } @@ -132,6 +139,20 @@ var ChromeCom = (function ChromeComClosure() { }); }; + function getEmbedderOrigin(callback) { + var origin = window === top ? location.origin : location.ancestorOrigins[0]; + if (origin === 'null') { + // file:-URLs, data-URLs, sandboxed frames, etc. + getParentOrigin(callback); + } else { + callback(origin); + } + } + + function getParentOrigin(callback) { + ChromeCom.request('getParentOrigin', null, callback); + } + function isAllowedFileSchemeAccess(callback) { ChromeCom.request('isAllowedFileSchemeAccess', null, callback); }