diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js
index 079c5330ec2a644eedcc883349735f087bf2a45c..6a767d48a289130376977c0fb224a0c70c4ff3c1 100644
--- a/apps/files/js/fileactions.js
+++ b/apps/files/js/fileactions.js
@@ -589,7 +589,7 @@
 							context.fileList.showFileBusyState(filename, false);
 						};
 
-						context.fileList.showFileBusyState(downloadFileaction, true);
+						context.fileList.showFileBusyState(filename, true);
 						OCA.Files.Files.handleDownload(url, disableLoadingState);
 					}
 				}
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index 9ab7609cc40a5d645f173a175ca3dbce75cc2e06..ae38511ec05789cc060e91e3f0dbdb9dac881118 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -295,7 +295,12 @@
 					}
 				};
 
-			OC.redirect(url + '&downloadStartSecret=' + randomToken);
+			if (url.indexOf('?') >= 0) {
+				url += '&';
+			} else {
+				url += '?';
+			}
+			OC.redirect(url + 'downloadStartSecret=' + randomToken);
 			OC.Util.waitFor(checkForDownloadCookie, 500);
 		}
 	};
diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js
index 6a57c56c3afb5ba16a893adb61ca48a86dcce48e..d29164c51366e584cc68ba0f98ac510724b478b1 100644
--- a/apps/files/tests/js/fileactionsSpec.js
+++ b/apps/files/tests/js/fileactionsSpec.js
@@ -227,7 +227,7 @@ describe('OCA.Files.FileActions tests', function() {
 				name: 'Test',
 				type: OCA.Files.FileActions.TYPE_INLINE,
 				mime: 'all',
-				icon: OC.imagePath('core', 'actions/test'), 
+				icon: OC.imagePath('core', 'actions/test'),
 				permissions: OC.PERMISSION_READ,
 				actionHandler: actionStub
 			});
@@ -556,4 +556,45 @@ describe('OCA.Files.FileActions tests', function() {
 			expect(handler.notCalled).toEqual(true);
 		});
 	});
+	describe('default actions', function() {
+		describe('download', function() {
+			it('redirects to URL and sets busy state to list', function() {
+				var handleDownloadStub = sinon.stub(OCA.Files.Files, 'handleDownload');
+				var busyStub = sinon.stub(fileList, 'showFileBusyState');
+				var fileData = {
+					id: 18,
+					type: 'file',
+					name: 'testName.txt',
+					mimetype: 'text/plain',
+					size: '1234',
+					etag: 'a01234c',
+					mtime: '123456',
+					permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE
+				};
+
+				// note: FileActions.display() is called implicitly
+				fileList.add(fileData);
+
+				var model = fileList.getModelForFile('testName.txt');
+
+				fileActions.registerDefaultActions();
+				fileActions.triggerAction('Download', model, fileList);
+
+				expect(busyStub.calledOnce).toEqual(true);
+				expect(busyStub.calledWith('testName.txt', true)).toEqual(true);
+				expect(handleDownloadStub.calledOnce).toEqual(true);
+				expect(handleDownloadStub.getCall(0).args[0]).toEqual(
+					OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=testName.txt'
+				);
+				busyStub.reset();
+				handleDownloadStub.yield();
+
+				expect(busyStub.calledOnce).toEqual(true);
+				expect(busyStub.calledWith('testName.txt', false)).toEqual(true);
+
+				busyStub.restore();
+				handleDownloadStub.restore();
+			});
+		});
+	});
 });
diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js
index f20ba03e2f1e90c850f18185ed745cfe9b53230f..30e6675c1556c3906aff0219a4b60bfab17e0e8a 100644
--- a/apps/files/tests/js/filesSpec.js
+++ b/apps/files/tests/js/filesSpec.js
@@ -87,4 +87,56 @@ describe('OCA.Files.Files tests', function() {
 			expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22test%20file.txt%22%2C%22abc.txt%22%5D');
 		});
 	});
+	describe('handleDownload', function() {
+		var redirectStub;
+		var cookieStub;
+		var clock;
+		var testUrl;
+
+		beforeEach(function() {
+			testUrl = 'http://example.com/owncloud/path/download.php';
+			redirectStub = sinon.stub(OC, 'redirect');
+			cookieStub = sinon.stub(OC.Util, 'isCookieSetToValue');
+			clock = sinon.useFakeTimers();
+		});
+		afterEach(function() {
+			redirectStub.restore();
+			cookieStub.restore();
+			clock.restore();
+		});
+
+		it('appends secret to url when no existing parameters', function() {
+			Files.handleDownload(testUrl);
+			expect(redirectStub.calledOnce).toEqual(true);
+			expect(redirectStub.getCall(0).args[0]).toContain(testUrl + '?downloadStartSecret=');
+		});
+		it('appends secret to url with existing parameters', function() {
+			Files.handleDownload(testUrl + '?test=1');
+			expect(redirectStub.calledOnce).toEqual(true);
+			expect(redirectStub.getCall(0).args[0]).toContain(testUrl + '?test=1&downloadStartSecret=');
+		});
+		it('sets cookie and calls callback when cookie appears', function() {
+			var callbackStub = sinon.stub();
+			var token;
+			Files.handleDownload(testUrl, callbackStub);
+			expect(redirectStub.calledOnce).toEqual(true);
+			token = OC.parseQueryString(redirectStub.getCall(0).args[0]).downloadStartSecret;
+			expect(token).toBeDefined();
+
+			expect(cookieStub.calledOnce).toEqual(true);
+			cookieStub.returns(false);
+			clock.tick(600);
+
+			expect(cookieStub.calledTwice).toEqual(true);
+			expect(cookieStub.getCall(1).args[0]).toEqual('ocDownloadStarted');
+			expect(cookieStub.getCall(1).args[1]).toEqual(token);
+			expect(callbackStub.notCalled).toEqual(true);
+
+			cookieStub.returns(true);
+			clock.tick(2000);
+
+			expect(cookieStub.callCount).toEqual(3);
+			expect(callbackStub.calledOnce).toEqual(true);
+		});
+	});
 });