From 058f143344c5903154e397d2170ed36cf6a3fb1b Mon Sep 17 00:00:00 2001 From: gasolin Date: Tue, 7 Jul 2015 11:49:50 +0800 Subject: [PATCH] Bug 1179174-[Notifications] use handleSystemMessageNotification to process bluetooth transfer complete notifications after reboot, r=ian, lissyx --- apps/system/js/bluetooth_transfer.js | 76 +++++++++++++++---- .../test/unit/bluetooth_transfer_test.js | 74 +++++++++++++++++- 2 files changed, 136 insertions(+), 14 deletions(-) diff --git a/apps/system/js/bluetooth_transfer.js b/apps/system/js/bluetooth_transfer.js index 926b57866376..8b8697462636 100644 --- a/apps/system/js/bluetooth_transfer.js +++ b/apps/system/js/bluetooth_transfer.js @@ -19,6 +19,7 @@ var BluetoothTransfer = { * @type {Boolean} turn on/off the console log */ onDebug: false, + bluetoothIcon: 'style/bluetooth_transfer/images/icon_bluetooth.png', get _deviceStorage() { return navigator.getDeviceStorage('sdcard'); @@ -35,6 +36,11 @@ var BluetoothTransfer = { /** * Initialize BluetoothTransfer module. * + * Service request handleSystemMessageNotification is used to filter + * and relay BluetoothTransfer related notifications handle event after + * reboot. Now only `_onTransferComplete` method generate notifications + * that need to be handled after reboot. + * * @public */ start: function bt_start() { @@ -67,6 +73,8 @@ var BluetoothTransfer = { Service.registerState('isSendFileQueueEmpty', this); Service.registerState('isFileTransferInProgress', this); + Service.request('handleSystemMessageNotification', + 'BluetoothTransfer', this); }, getDeviceName: function bt_getDeviceName(address) { @@ -168,18 +176,16 @@ var BluetoothTransfer = { // received. this.debug('show receive confirm dialog'); var address = evt.address; - var icon = 'style/bluetooth_transfer/images/icon_bluetooth.png'; this.getDeviceName(address).then((deviceName) => { var title = { id: 'transfer-confirmation-title', args: { deviceName: deviceName } }; - var body = 'transfer-confirmation-description'; NotificationHelper.send(title, { - 'bodyL10n': body, - 'icon': icon + 'bodyL10n': 'transfer-confirmation-description', + 'icon': this.bluetoothIcon }).then((notification) => { notification.addEventListener('click', () => { UtilityTray.hide(); @@ -205,8 +211,7 @@ var BluetoothTransfer = { }; this.getDeviceName(address).then(function(deviceName) { - Service.request('showCustomDialog', - 'acceptFileTransfer', + Service.request('showCustomDialog', 'acceptFileTransfer', { id: 'wantToReceiveFile', args: { @@ -264,9 +269,8 @@ var BluetoothTransfer = { } }; - var body = msg; Service.request('showCustomDialog', - 'cannotReceiveFile', body, confirm, null); + 'cannotReceiveFile', msg, confirm, null); }, checkStorageSpace: function bt_checkStorageSpace(fileSize, callback) { @@ -466,16 +470,21 @@ var BluetoothTransfer = { } }, + /** + * Create notification when transfer complete. + * + * @param {Object} evt bluetooth-opp-transfer-complete event + */ _onTransferComplete: function bt__onTransferComplete(evt) { var transferInfo = evt.detail.transferInfo; // Remove transferring progress this.removeProgress(transferInfo); - var icon = 'style/bluetooth_transfer/images/icon_bluetooth.png'; // Show notification var nData = { titleL10n: null, - icon: icon, + icon: this.bluetoothIcon, + transferInfo: null, onclick: null }; @@ -483,6 +492,7 @@ var BluetoothTransfer = { if (transferInfo.received) { // Received file can be opened only nData.titleL10n = 'transferFinished-receivedSuccessful-title'; + nData.transferInfo = transferInfo; nData.onclick = this.openReceivedFile.bind(this, transferInfo); } else { nData.titleL10n = 'transferFinished-sentSuccessful-title'; @@ -496,17 +506,21 @@ var BluetoothTransfer = { } var l10nArgs = { - icon: nData.icon + icon: nData.icon, + data: { + systemMessageTarget: 'BluetoothTransfer' + } }; if (transferInfo.fileName) { l10nArgs.body = transferInfo.fileName; + // put original message in data for reference + l10nArgs.data.transferInfo = nData.transferInfo; } else { l10nArgs.bodyL10n = 'unknown-file'; } var promise = NotificationHelper.send(nData.titleL10n, l10nArgs); - if (nData.onclick) { promise.then(function(notification) { notification.addEventListener('click', nData.onclick); @@ -530,6 +544,42 @@ var BluetoothTransfer = { detail: details})); }, + /** + * Handle related system notification message operation after reboot. + * Need close notification message by ourself. + * + * @param {Object} message system notification message + */ + handleSystemMessageNotification: function(message) { + this.debug('Received system message: ' + JSON.stringify(message)); + if (message.data && message.data.transferInfo) { + var evt = { + fileName: message.data.transferInfo.fileName, + contentType: message.data.transferInfo.contentType + }; + this.openReceivedFile(evt); + } else { + console.error('The notification does not carry correct data'); + } + this.closeSystemMessageNotification(message); + }, + + /** + * Close the system notification message. + * + * @param {Object} message system notification message + */ + closeSystemMessageNotification: function(message) { + Notification.get({ tag: message.tag }).then(notifs => { + notifs.forEach(notif => { + // check on the body + if (notif.body === message.body) { + notif.close && notif.close(); + } + }); + }); + }, + summarizeSentFilesReport: function bt_summarizeSentFilesReport(transferInfo) { // Ignore received files @@ -571,7 +621,7 @@ var BluetoothTransfer = { numUnsuccessful: numUnsuccessful } }, - 'icon': 'style/bluetooth_transfer/images/icon_bluetooth.png' + 'icon': this.bluetoothIcon }); // Remove the finished sending task from the queue diff --git a/apps/system/test/unit/bluetooth_transfer_test.js b/apps/system/test/unit/bluetooth_transfer_test.js index 0d4d0684f58f..45f840d2fd63 100644 --- a/apps/system/test/unit/bluetooth_transfer_test.js +++ b/apps/system/test/unit/bluetooth_transfer_test.js @@ -1,6 +1,6 @@ /* global MocksHelper, MockNavigatormozSetMessageHandler, MockNavigatorGetDeviceStorage, MockL10n, MockBTAdapter, MockDOMRequest, - BluetoothTransfer, MockNotificationHelper, MockUtilityTray, + BluetoothTransfer, MockNotificationHelper, MockNotification, MockUtilityTray, NotificationHelper, MockCustomDialog, MimeMapper, mockMozActivityInstance, Service, MockService */ 'use strict'; @@ -12,6 +12,7 @@ require('/test/unit/mock_navigator_get_device_storage.js'); require('/shared/test/unit/mocks/mock_navigator_moz_bluetooth_v2.js'); require('/shared/test/unit/mocks/mock_l10n.js'); require('/shared/test/unit/mocks/mock_notification_helper.js'); +require('/shared/test/unit/mocks/mock_notification.js'); require('/shared/js/mime_mapper.js'); require('/test/unit/mock_utility_tray.js'); require('/test/unit/mock_nfc_handover_manager.js'); @@ -34,6 +35,7 @@ suite('system/bluetooth_transfer', function() { var realSetMessageHandler; var realNavigatorGetDeviceStorage; var realL10n; + var realNotification; var real_sendingFilesQueue; var fake_sendingFilesQueue; @@ -48,6 +50,9 @@ suite('system/bluetooth_transfer', function() { realL10n = navigator.mozL10n; navigator.mozL10n = MockL10n; + realNotification = window.Notification; + window.Notification = MockNotification; + MockNavigatormozSetMessageHandler.mSetup(); requireApp('system/js/bluetooth_transfer.js', done); @@ -58,6 +63,7 @@ suite('system/bluetooth_transfer', function() { navigator.mozSetMessageHandler = realSetMessageHandler; navigator.getDeviceStorage = realNavigatorGetDeviceStorage; navigator.mozL10n = realL10n; + window.Notification = realNotification; }); suite('Initialize', function() { @@ -93,6 +99,13 @@ suite('system/bluetooth_transfer', function() { assert.ok(window.navigator.mozSetMessageHandler.calledWith( 'bluetooth-opp-update-progress')); }); + + test('Service Request called', function() { + assert.isTrue(MockService.request.calledOnce); + assert.isTrue(MockService.request.calledWith( + 'handleSystemMessageNotification', 'BluetoothTransfer', + BluetoothTransfer)); + }); }); suite('UI', function() { @@ -319,6 +332,7 @@ suite('system/bluetooth_transfer', function() { MockNotificationHelper.mOptions.icon, 'style/bluetooth_transfer/images/icon_bluetooth.png' ); + NotificationHelper.mEmit('click'); assert.isTrue(MockUtilityTray.hide.called); assert.isTrue(BluetoothTransfer.showReceivePrompt.called); @@ -813,5 +827,63 @@ suite('system/bluetooth_transfer', function() { }); }); }); + + suite('handleSystemMessageNotification behavior', function() { + test('calls openReceivedFile', function() { + var message = { + body: 'someFile.txt', + data: { + systemMessageTarget: 'BluetoothTransfer', + transferInfo: { + 'fileName': 'someFile.txt', + 'contentType': '' + }, + } + }; + this.sinon.spy(BluetoothTransfer, 'openReceivedFile'); + this.sinon.spy(BluetoothTransfer, 'closeSystemMessageNotification'); + BluetoothTransfer.handleSystemMessageNotification(message); + + assert.isTrue(BluetoothTransfer.openReceivedFile.calledOnce); + assert.isTrue( + BluetoothTransfer.closeSystemMessageNotification.calledOnce); + }); + }); + + suite('closeSystemMessageNotification behavior', function() { + var notifCloseSpy, notificationGetStub; + var notification = { + body: 'fake', + data: { + systemMessageTarget: 'BluetoothTransfer' + }, + close: function() {} + }; + + setup(function() { + notifCloseSpy = this.sinon.spy(notification, 'close'); + notificationGetStub = function notificationGet() { + return { + then: function(cb) { + cb && cb([ notification ]); + } + }; + }; + this.sinon.stub(window.Notification, 'get', notificationGetStub); + }); + + test('closes notification by body', function() { + var tag = notification.tag; + notification.tag = undefined; + + BluetoothTransfer.closeSystemMessageNotification(notification); + assert.isTrue(window.Notification.get.calledOnce); + assert.isTrue(window.Notification.get.calledWith( + { tag: notification.tag})); + assert.isTrue(notifCloseSpy.calledOnce); + + notification.tag = tag; + }); + }); }); });