diff options
author | diosmosis <diosmosis@users.noreply.github.com> | 2018-10-03 08:59:54 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-03 08:59:54 +0300 |
commit | 67eaa2c0381933d5e38180a2159044893447acca (patch) | |
tree | 6810978ef7295aeeaeb2256b95712111cea07c96 /plugins/Overlay/javascripts/Piwik_Overlay.js | |
parent | ae872e501015ec5ed5a538c23f6e090ce3089c66 (diff) |
Use postMessage instead of directly making API calls in the overlay iframe. (#13446)
* Use postMessage instead of directly making API calls in the overlay iframe.
* Make sure it will work when Matomo is on a subfolder.
* Increase overlay security with domain and method whitelists.
* Try to fix UI test.
* Fix tests + UI test blacklist check.
* broadcast.getValuesFromUrl does not decode URL params.
Diffstat (limited to 'plugins/Overlay/javascripts/Piwik_Overlay.js')
-rw-r--r-- | plugins/Overlay/javascripts/Piwik_Overlay.js | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/plugins/Overlay/javascripts/Piwik_Overlay.js b/plugins/Overlay/javascripts/Piwik_Overlay.js index afcbc268ad..4c06f75cd0 100644 --- a/plugins/Overlay/javascripts/Piwik_Overlay.js +++ b/plugins/Overlay/javascripts/Piwik_Overlay.js @@ -7,6 +7,14 @@ var Piwik_Overlay = (function () { + var DOMAIN_PARSE_REGEX = /^http(s)?:\/\/(www\.)?([^\/]*)/i; + var ORIGIN_PARSE_REGEX = /^https?:\/\/[^\/]*/; + var ALLOWED_API_REQUEST_WHITELIST = [ + 'Overlay.getTranslations', + 'Overlay.getExcludedQueryParameters', + 'Overlay.getFollowingPages', + ]; + var $body, $iframe, $sidebar, $main, $location, $loading, $errorNotLoading; var $rowEvolutionLink, $transitionsLink, $visitorLogLink; @@ -18,6 +26,7 @@ var Piwik_Overlay = (function () { var iframeCurrentPageNormalized = ''; var iframeCurrentActionLabel = ''; var updateComesFromInsideFrame = false; + var iframeOrigin = ''; /** Load the sidebar for a url */ function loadSidebar(currentUrl) { @@ -26,7 +35,7 @@ var Piwik_Overlay = (function () { $location.html(' ').unbind('mouseenter').unbind('mouseleave'); iframeCurrentPage = currentUrl; - iframeDomain = currentUrl.match(/http(s)?:\/\/(www\.)?([^\/]*)/i)[3]; + iframeDomain = currentUrl.match(DOMAIN_PARSE_REGEX)[3]; var params = { module: 'Overlay', @@ -135,11 +144,31 @@ var Piwik_Overlay = (function () { return location; } + function setIframeOrigin(location) { + iframeOrigin = location.match(ORIGIN_PARSE_REGEX)[0]; + + // unset iframe origin if it is not one of the site URLs + var validSiteOrigins = Piwik_Overlay.siteUrls.map(function (url) { + return url.match(ORIGIN_PARSE_REGEX)[0]; + }); + + if (iframeOrigin && validSiteOrigins.indexOf(iframeOrigin) === -1) { + try { + console.log('Found invalid iframe origin in hash URL: ' + iframeOrigin); + } catch (e) { + // ignore + } + iframeOrigin = null; + } + } + /** $.history callback for hash change */ function hashChangeCallback(urlHash) { var location = getOverlayLocationFromHash(urlHash); location = Overlay_Helper.decodeFrameUrl(location); + setIframeOrigin(location); + if (location == iframeCurrentPageNormalized) { return; } @@ -158,6 +187,54 @@ var Piwik_Overlay = (function () { updateComesFromInsideFrame = false; } + function handleApiRequests() { + window.addEventListener("message", function (event) { + if (event.origin !== iframeOrigin || !iframeOrigin) { + return; + } + + var strData = event.data.split(':', 3); + if (strData[0] !== 'overlay.call') { + return; + } + + var requestId = strData[1]; + var url = decodeURIComponent(strData[2]); + + var params = broadcast.getValuesFromUrl(url); + Object.keys(params).forEach(function (name) { + params[name] = decodeURIComponent(params[name]); + }); + params.module = 'API'; + params.action = 'index'; + + if (ALLOWED_API_REQUEST_WHITELIST.indexOf(params.method) === -1) { + sendResponse({ + result: 'error', + message: "'" + params.method + "' method is not allowed.", + }); + return; + } + + angular.element(document).injector().invoke(['piwikApi', function (piwikApi) { + piwikApi.fetch(params) + .then(function (response) { + sendResponse(response); + }).catch(function (err) { + sendResponse({ + result: 'error', + message: err.message, + }); + }); + }]); + + function sendResponse(data) { + var message = 'overlay.response:' + requestId + ':' + encodeURIComponent(JSON.stringify(data)); + $iframe[0].contentWindow.postMessage(message, iframeOrigin); + } + }, false); + } + return { /** This method is called when Overlay loads */ @@ -181,7 +258,6 @@ var Piwik_Overlay = (function () { $visitorLogLink = $('#overlaySegmentedVisitorLog'); adjustDimensions(); - showLoading(); // apply initial dimensions @@ -206,6 +282,8 @@ var Piwik_Overlay = (function () { hashChangeCallback(''); } + handleApiRequests(); + // handle date selection var $select = $('select#overlayDateRangeSelect').change(function () { var parts = $(this).val().split(';'); @@ -286,6 +364,7 @@ var Piwik_Overlay = (function () { window.location.replace(newLocation); } else { // happens when the url is changed by hand or when the l parameter is there on page load + setIframeOrigin(currentUrl); loadSidebar(currentUrl); } } |