[chrome-gnome-shell] sync: avoid synchronization of disabled extensions during sleep state.



commit 4e772ae62e43328a94116fd5d21f0b395bdd13d4
Author: Yuri Konotopov <ykonotopov gnome org>
Date:   Sun Mar 19 13:21:03 2017 +0400

    sync: avoid synchronization of disabled extensions during sleep state.
    
    When entering sleep state GNOME Shell disables all extensions and
    re-enables them again when returning to active state. Let's listen to
    idle events and prevent disabled extensions to be synchronized.
    Also implemented queue of changing state extensions that will lower
    synchronization events overhead.
    
    Fixes: https://github.com/nE0sIghT/chrome-gnome-shell-mirror/issues/45

 extension/include/sync.js |  169 +++++++++++++++++++++++++++++++++------------
 extension/manifest.json   |    5 +-
 extension/options.js      |   69 +++++++++++++++----
 3 files changed, 184 insertions(+), 59 deletions(-)
---
diff --git a/extension/include/sync.js b/extension/include/sync.js
index fb38b07..8cee5c0 100644
--- a/extension/include/sync.js
+++ b/extension/include/sync.js
@@ -12,15 +12,70 @@
  * Main object that handles extensions synchronization with remote storage.
  */
 GSC.sync = (function($) {
+       var enabled = true;
+       var extensionChangedTimeout = false;
+       var extensionChangedQueue = {};
+
+       const SYNC_QUEUE_TIMEOUT = 3000;
+
        /*
         * Initialization rutines.
         */
        function init() {
                if(!COMPAT.SYNC_STORAGE)
                {
+                       enabled = false;
                        return;
                }
 
+               function onIdleStateChanged(state) {
+                       if (state === 'locked')
+                       {
+                               enabled = false;
+
+                               // Remove all disabled extensions from queue
+                               $.each(extensionChangedQueue, function(extensionId, extension) {
+                                       if(extension.state == EXTENSION_STATE.DISABLED)
+                                       {
+                                               delete extensionChangedQueue[extensionId];
+                                       }
+                               });
+                       }
+                       else if (state === 'active')
+                       {
+                               enabled = true;
+                       }
+               }
+
+               chrome.permissions.contains({
+                       permissions: ["idle"]
+               }, function (result) {
+                       if(result)
+                       {
+                               chrome.idle.onStateChanged.addListener(onIdleStateChanged);
+                       }
+                       else
+                       {
+                               enabled = false;
+                       }
+               });
+
+               chrome.permissions.onAdded.addListener(function(permissions) {
+                       if(permissions.permissions && permissions.permissions.indexOf('idle') !== -1)
+                       {
+                               enabled = true;
+                               chrome.idle.onStateChanged.addListener(onIdleStateChanged);
+                       }
+               });
+
+               chrome.permissions.onRemoved.addListener(function(permissions) {
+                       if(permissions.permissions && permissions.permissions.indexOf('idle') !== -1)
+                       {
+                               enabled = false;
+                               chrome.idle.onStateChanged.removeListener(onIdleStateChanged);
+                       }
+               });
+
                function onNotificationAction(notificationId, buttonIndex) {
                        if (notificationId !== NOTIFICATION_SYNC_FAILED)
                        {
@@ -182,47 +237,55 @@ GSC.sync = (function($) {
 
        /*
         * Synchronize local changed extensions to remote list.
-        * 
-        * @param extension - extension object:
-        * {
-        *      uuid:   extension uuid,
-        *      name:   extension name,
-        *      state:  extension state
-        * }
         */
-       function localExtensionChanged(extension) {
-               if($.inArray(extension.state, [EXTENSION_STATE.ENABLED, EXTENSION_STATE.DISABLED, 
EXTENSION_STATE.UNINSTALLED]) !== -1)
+       function localExtensionsChanged() {
+               extensionChangedTimeout = false;
+
+               if (!$.isEmptyObject(extensionChangedQueue))
                {
-                       chrome.storage.sync.get({
-                               extensions: {}
-                       }, function (options) {
-                               GSC.sendNativeRequest({
-                                       execute:        'getExtensionInfo',
-                                       uuid:           extension.uuid
-                               }, function(response) {
-                                       // Extension can be uninstalled already
-                                       if(response && response.extensionInfo && 
!$.isEmptyObject(response.extensionInfo))
-                                       {
-                                               extension = response.extensionInfo;
-                                       }
+                       GSC.sendNativeRequest({
+                               execute: 'listExtensions'
+                       }, function (response) {
+                               if (response && response.success && response.extensions)
+                               {
+                                       chrome.storage.sync.get({
+                                               extensions: {}
+                                       }, function (options) {
+                                               $.each(extensionChangedQueue, function (extensionId, 
extension) {
+                                                       if ($.inArray(extension.state, 
[EXTENSION_STATE.ENABLED, EXTENSION_STATE.DISABLED, EXTENSION_STATE.UNINSTALLED]) !== -1)
+                                                       {
+                                                               // Extension can be uninstalled already
+                                                               if (response.extensions[extensionId] && 
!$.isEmptyObject(response.extensions[extensionId]))
+                                                               {
+                                                                       extension = 
response.extensions[extensionId];
+                                                               }
 
-                                       if(extension.state === EXTENSION_STATE.UNINSTALLED && 
options.extensions[extension.uuid])
-                                       {
-                                               delete options.extensions[extension.uuid];
-                                       }
-                                       else
-                                       {
-                                               options.extensions[extension.uuid] = {
-                                                       uuid:   extension.uuid,
-                                                       name:   extension.name,
-                                                       state:  extension.state
-                                               };
-                                       }
+                                                               if (extension.state === 
EXTENSION_STATE.UNINSTALLED && options.extensions[extension.uuid])
+                                                               {
+                                                                       delete 
options.extensions[extension.uuid];
+                                                               }
+                                                               else
+                                                               {
+                                                                       options.extensions[extension.uuid] = {
+                                                                               uuid: extension.uuid,
+                                                                               name: extension.name,
+                                                                               state: extension.state
+                                                                       };
+                                                               }
+                                                       }
+                                               });
 
-                                       chrome.storage.sync.set({
-                                               extensions: options.extensions
+                                               chrome.storage.sync.set({
+                                                       extensions: options.extensions
+                                               });
+
+                                               extensionChangedQueue = {};
                                        });
-                               });
+                               }
+                               else
+                               {
+                                       createSyncFailedNotification();
+                               }
                        });
                }
        }
@@ -233,6 +296,7 @@ GSC.sync = (function($) {
         * @param remoteExtensions - (optional) remote extensions list
         */
        function remoteExtensionsChanged(remoteExtensions) {
+
                getExtensions($.Deferred().done(function(extensions) {
                        var enableExtensions = [];
                        $.each(extensions, function(uuid, extension) {
@@ -308,17 +372,26 @@ GSC.sync = (function($) {
         */
        function onExtensionChanged(request)
        {
-               if(!COMPAT.SYNC_STORAGE)
+               if(!COMPAT.SYNC_STORAGE || !enabled)
                {
                        return;
                }
 
-               runIfSyncEnabled(function() {
-                       localExtensionChanged({
-                               uuid:   request.parameters[EXTENSION_CHANGED_UUID],
-                               state:  request.parameters[EXTENSION_CHANGED_STATE],
-                               error:  request.parameters[EXTENSION_CHANGED_ERROR]
-                       });
+               runIfSyncEnabled(() => {
+                       if (extensionChangedTimeout)
+                       {
+                               clearTimeout(extensionChangedTimeout);
+                       }
+
+                       extensionChangedQueue[request.parameters[EXTENSION_CHANGED_UUID]] = {
+                               uuid: request.parameters[EXTENSION_CHANGED_UUID],
+                               state: request.parameters[EXTENSION_CHANGED_STATE],
+                               error: request.parameters[EXTENSION_CHANGED_ERROR]
+                       };
+
+                       extensionChangedTimeout = setTimeout(function () {
+                               localExtensionsChanged();
+                       }, SYNC_QUEUE_TIMEOUT);
                });
        }
 
@@ -349,7 +422,15 @@ GSC.sync = (function($) {
                }, function (options) {
                        if (options.syncExtensions)
                        {
-                               callback();
+                               chrome.permissions.contains({
+                                       permissions: ["idle"]
+                               }, function (result) {
+                                       if (result)
+                                       {
+                                               callback();
+                                       }
+                               });
+
                        }
                });
        }
diff --git a/extension/manifest.json b/extension/manifest.json
index 105472c..91d0307 100644
--- a/extension/manifest.json
+++ b/extension/manifest.json
@@ -47,6 +47,9 @@
     "storage",
     "https://extensions.gnome.org/";
   ],
-  "optional_permissions": [ "webRequest" ],
+  "optional_permissions": [
+    "idle",
+    "webRequest"
+  ],
   "web_accessible_resources": ["include/sweettooth-api.js"]
 }
diff --git a/extension/options.js b/extension/options.js
index 7e1266a..56547e5 100644
--- a/extension/options.js
+++ b/extension/options.js
@@ -100,7 +100,18 @@ function restore_options()
        {
                updateSynchronizationStatus();
                chrome.storage.local.get(DEFAULT_LOCAL_OPTIONS, function (items) {
-                       setSyncExtensions(items.syncExtensions);
+                       if(items.syncExtensions)
+                       {
+                               chrome.permissions.contains({
+                                       permissions: ["idle"]
+                               }, function (result) {
+                                       setSyncExtensions(result);
+                               });
+                       }
+                       else
+                       {
+                               setSyncExtensions(false);
+                       }
                });
        }
        else
@@ -204,6 +215,40 @@ function handleWebrequestPermission()
        }
 }
 
+function handleSynchronize()
+{
+       if($('#synchronize_extensions_yes').is(':checked'))
+       {
+               chrome.permissions.request({
+                       permissions: ["idle"]
+               }, function(granted) {
+                       if(granted)
+                       {
+                               chrome.storage.sync.get({
+                                       extensions: {}
+                               }, function (options) {
+                                       if(!$.isEmptyObject(options.extensions))
+                                       {
+                                               document.getElementById('syncChoice').showModal();
+                                       }
+                               });
+                       }
+                       else
+                       {
+                               setSyncExtensions(false);
+                       }
+               });
+       }
+       else
+       {
+               chrome.permissions.remove({
+                       permissions: ["idle"]
+               }, function(removed) {
+                       setSyncExtensions(!removed);
+               });
+       }
+}
+
 function updateSynchronizationStatus()
 {
        GSC.sync.getExtensions($.Deferred().done(function (extensions) {
@@ -263,26 +308,22 @@ i18n();
 
 document.addEventListener('DOMContentLoaded', restore_options);
 document.getElementById('save').addEventListener('click', save_options);
+
 $.each(document.getElementsByName('show_network_errors'), function(index, control) {
        control.addEventListener('change', handleWebrequestPermission);
 });
 
+$.each(document.getElementsByName('synchronize_extensions'), function(index, control) {
+       control.addEventListener('change', handleSynchronize);
+});
+
 document.getElementById('syncChoice').addEventListener('close', function() {
        if(document.getElementById('syncChoice').returnValue === 'cancel')
        {
-               $('#synchronize_extensions_no').prop('checked', 'checked');
-       }
-});
-$('input[type="radio"][name="synchronize_extensions"]').change(function() {
-       if($('#synchronize_extensions_yes').is(':checked'))
-       {
-               chrome.storage.sync.get({
-                       extensions: {}
-               }, function (options) {
-                       if(!$.isEmptyObject(options.extensions))
-                       {
-                               document.getElementById('syncChoice').showModal();
-                       }
+               chrome.permissions.remove({
+                       permissions: ["idle"]
+               }, function(removed) {
+                       setSyncExtensions(!removed);
                });
        }
 });


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]