diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index 12038ff1bf50..53d91b4be954 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -87,8 +87,11 @@ void OnPdfResourceIntercepted( // by the webui page. // chrome://pdf-viewer/index.html?src=https://somepage/123.pdf content::NavigationController::LoadURLParams params( - GURL(base::StringPrintf("%sindex.html?%s=%s", kPdfViewerUIOrigin, - kPdfPluginSrc, original_url.spec().c_str()))); + GURL(base::StringPrintf( + "%sindex.html?%s=%s", + kPdfViewerUIOrigin, + kPdfPluginSrc, + net::EscapeUrlEncodedData(original_url.spec(), false).c_str()))); web_contents->GetController().LoadURLWithParams(params); } diff --git a/atom/browser/atom_web_ui_controller_factory.cc b/atom/browser/atom_web_ui_controller_factory.cc index ef8b2785ae55..d113e656084a 100644 --- a/atom/browser/atom_web_ui_controller_factory.cc +++ b/atom/browser/atom_web_ui_controller_factory.cc @@ -11,6 +11,7 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "content/public/browser/web_contents.h" +#include "net/base/escape.h" namespace atom { @@ -52,9 +53,15 @@ AtomWebUIControllerFactory::CreateWebUIControllerForURL(content::WebUI* web_ui, base::StringPairs toplevel_params; base::SplitStringIntoKeyValuePairs(url.query(), '=', '&', &toplevel_params); std::string stream_id, src; + + const net::UnescapeRule::Type unescape_rules = + net::UnescapeRule::SPACES | net::UnescapeRule::PATH_SEPARATORS | + net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | + net::UnescapeRule::REPLACE_PLUS_WITH_SPACE; + for (const auto& param : toplevel_params) { if (param.first == kPdfPluginSrc) { - src = param.second; + src = net::UnescapeURLComponent(param.second, unescape_rules); } } if (url.has_ref()) { diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index e4a9f04d78ef..2f9f2b2795ad 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -982,6 +982,15 @@ describe('chromium feature', function () { protocol: 'file', slashes: true }) + const pdfSourceWithParams = url.format({ + pathname: path.join(fixtures, 'assets', 'cat.pdf').replace(/\\/g, '/'), + query: { + a: 1, + b: 2 + }, + protocol: 'file', + slashes: true + }) function createBrowserWindow ({plugins}) { w = new BrowserWindow({ @@ -1009,6 +1018,24 @@ describe('chromium feature', function () { w.webContents.loadURL(pdfSource) }) + it('opens a pdf link given params, the query string should be escaped', function (done) { + createBrowserWindow({plugins: true}) + ipcMain.once('pdf-loaded', function (event, state) { + assert.equal(state, 'success') + done() + }) + w.webContents.on('page-title-updated', function () { + const parsedURL = url.parse(w.webContents.getURL(), true) + assert.equal(parsedURL.protocol, 'chrome:') + assert.equal(parsedURL.hostname, 'pdf-viewer') + assert.equal(parsedURL.query.src, pdfSourceWithParams) + assert.equal(parsedURL.query.b, undefined) + assert.equal(parsedURL.search, `?src=${pdfSource}%3Fa%3D1%26b%3D2`) + assert.equal(w.webContents.getTitle(), 'cat.pdf') + }) + w.webContents.loadURL(pdfSourceWithParams) + }) + it('should download a pdf when plugins are disabled', function (done) { createBrowserWindow({plugins: false}) ipcRenderer.sendSync('set-download-option', false, false)