[chrome-gnome-shell/feature/firefox: 1/2] Added initial Firefox support.



commit c641511dcef9af8a7990b1c11912e19acf685d5d
Author: Yuri Konotopov <ykonotopov gmail com>
Date:   Fri Nov 18 19:23:15 2016 +0300

    Added initial Firefox support.
    
    Current stable Firefox 50 still missing some used APIs, but mostly usable.

 CMakeLists.txt                                     |   31 ++++++++++-
 .../org.gnome.chrome_gnome_shell.firefox.json      |    3 +
 extension/extension.html                           |    1 +
 extension/include/compat-common.js                 |   56 ++++++++++++++++++++
 extension/include/compat-content-script.js         |   48 +++++++++++++++++
 extension/include/constants.js                     |    5 ++-
 extension/include/notifications.js                 |   14 ++++--
 extension/include/sync.js                          |    7 +--
 extension/manifest.firefox.json                    |   16 ++++++
 extension/manifest.json                            |    1 +
 extension/options.html                             |    1 +
 extension/options.js                               |   17 ++++++-
 12 files changed, 188 insertions(+), 12 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f6e27ad..3271e11 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,6 +20,7 @@ set(EXTENSION_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/extension)
 set(EXTENSION_BUILD_DIR ${CMAKE_BINARY_DIR}/extension)
 set(CHROME_BUILD_DIR ${EXTENSION_BUILD_DIR}/chrome)
 set(OPERA_BUILD_DIR ${EXTENSION_BUILD_DIR}/opera)
+set(FIREFOX_BUILD_DIR ${EXTENSION_BUILD_DIR}/firefox)
 
 # Options
 option(BUILD_EXTENSION         "Build extension zip package"   TRUE)
@@ -91,6 +92,7 @@ if(BUILD_EXTENSION OR BUILD_CONNECTOR)
        find_program_ex(sha256sum gsha256sum FATAL_ERROR)
        find_program_ex(head ghead FATAL_ERROR)
        find_program_ex(tr gtr FATAL_ERROR)
+       find_program_ex(jq FATAL_ERROR)
 
        # https://github.com/adobe/chromium/blob/master/chrome/common/extensions/extension.cc#L696
        # http://stackoverflow.com/questions/23873623/obtaining-chrome-extension-id-for-development
@@ -116,10 +118,13 @@ if(BUILD_EXTENSION)
        find_program_ex(7z FATAL_ERROR)
 
        file(COPY "${EXTENSION_SOURCES}/" DESTINATION "${CHROME_BUILD_DIR}"
-               PATTERN "manifest.json" EXCLUDE)
+               PATTERN "manifest*.json" EXCLUDE)
 
        file(COPY "${EXTENSION_SOURCES}/" DESTINATION "${OPERA_BUILD_DIR}"
-               PATTERN "manifest.json" EXCLUDE)
+               PATTERN "manifest*.json" EXCLUDE)
+
+       file(COPY "${EXTENSION_SOURCES}/" DESTINATION "${FIREFOX_BUILD_DIR}"
+               PATTERN "manifest*.json" EXCLUDE)
 
        set(PUBLIC_KEY ${CHROME_EXTENSION_KEY})
        configure_file("${EXTENSION_SOURCES}/manifest.json" "${CHROME_BUILD_DIR}/")
@@ -135,6 +140,12 @@ if(BUILD_EXTENSION)
        add_custom_target(opera-extension ALL
                COMMAND "${7Z_EXECUTABLE}" a -tzip "${CMAKE_BINARY_DIR}/extension-opera.zip" ./
                WORKING_DIRECTORY "${OPERA_BUILD_DIR}")
+       add_custom_target(firefox-extension ALL
+               COMMAND "${JQ_EXECUTABLE}" -s "'add|del(.key)'"
+                               '${EXTENSION_SOURCES}/manifest.json' 
'${EXTENSION_SOURCES}/manifest.firefox.json'
+                               > "${FIREFOX_BUILD_DIR}/manifest.json"
+               COMMAND "${7Z_EXECUTABLE}" a -tzip "${CMAKE_BINARY_DIR}/extension-opera.zip" ./
+               WORKING_DIRECTORY "${FIREFOX_BUILD_DIR}")
 endif(BUILD_EXTENSION)
 
 if(BUILD_CONNECTOR)
@@ -151,6 +162,16 @@ if(BUILD_CONNECTOR)
        configure_file("${CMAKE_CURRENT_SOURCE_DIR}/policies/chrome-gnome-shell.json"
                        "${CMAKE_BINARY_DIR}/")
 
+       add_custom_target(firefox-native-manifest ALL
+                       COMMAND "${JQ_EXECUTABLE}" -s "'add|del(.allowed_origins)'"
+                               "${CMAKE_BINARY_DIR}/org.gnome.chrome_gnome_shell.json"
+                               
"${CMAKE_CURRENT_SOURCE_DIR}/connector/org.gnome.chrome_gnome_shell.firefox.json"
+                               > "${CMAKE_BINARY_DIR}/org.gnome.chrome_gnome_shell.firefox.json"
+                       COMMAND "${JQ_EXECUTABLE}" -s "'add|del(.allowed_origins)'"
+                               "${CMAKE_BINARY_DIR}/io.github.ne0sight.gs_chrome_connector.json"
+                               
"${CMAKE_CURRENT_SOURCE_DIR}/connector/org.gnome.chrome_gnome_shell.firefox.json"
+                               > "${CMAKE_BINARY_DIR}/io.github.ne0sight.gs_chrome_connector.firefox.json")
+
        if(USE_DEBIAN_LAYOUT)
                set(DISTUTILS_EXTRA_ARGS "--install-layout=deb")
        else()
@@ -172,6 +193,12 @@ if(BUILD_CONNECTOR)
        install(FILES "${CMAKE_BINARY_DIR}/io.github.ne0sight.gs_chrome_connector.json" DESTINATION 
"/etc/opt/chrome/native-messaging-hosts/")
        install(FILES "${CMAKE_BINARY_DIR}/org.gnome.chrome_gnome_shell.json" DESTINATION 
"/etc/chromium/native-messaging-hosts/")
        install(FILES "${CMAKE_BINARY_DIR}/org.gnome.chrome_gnome_shell.json" DESTINATION 
"/etc/opt/chrome/native-messaging-hosts/")
+       install(FILES "${CMAKE_BINARY_DIR}/io.github.ne0sight.gs_chrome_connector.firefox.json"
+                       DESTINATION "${CMAKE_INSTALL_LIBDIR}/mozilla/native-messaging-hosts/"
+                       RENAME "io.github.ne0sight.gs_chrome_connector.json")
+       install(FILES "${CMAKE_BINARY_DIR}/org.gnome.chrome_gnome_shell.firefox.json"
+                       DESTINATION "${CMAKE_INSTALL_LIBDIR}/mozilla/native-messaging-hosts/"
+                       RENAME "org.gnome.chrome_gnome_shell.json")
        install(FILES "${CMAKE_BINARY_DIR}/chrome-gnome-shell.json" DESTINATION 
"/etc/opt/chrome/policies/managed/")
        install(FILES "${CMAKE_BINARY_DIR}/chrome-gnome-shell.json" DESTINATION 
"/etc/chromium/policies/managed/")
 
diff --git a/connector/org.gnome.chrome_gnome_shell.firefox.json 
b/connector/org.gnome.chrome_gnome_shell.firefox.json
new file mode 100644
index 0000000..d93ca73
--- /dev/null
+++ b/connector/org.gnome.chrome_gnome_shell.firefox.json
@@ -0,0 +1,3 @@
+{
+       "allowed_extensions": [ "chrome-gnome-shell gnome org" ]
+}
diff --git a/extension/extension.html b/extension/extension.html
index 6a901b8..c0b9f0c 100644
--- a/extension/extension.html
+++ b/extension/extension.html
@@ -10,6 +10,7 @@
                <script src="include/external/jquery-2.1.4.js"></script>
                <script src="include/i18n.js"></script>
                <script src="include/constants.js"></script>
+               <script src="include/compat-common.js"></script>
                <script src="include/gsc.js"></script>
                <script src="include/notifications.js"></script>
                <script src="include/update.js"></script>
diff --git a/extension/include/compat-common.js b/extension/include/compat-common.js
new file mode 100644
index 0000000..aaa5276
--- /dev/null
+++ b/extension/include/compat-common.js
@@ -0,0 +1,56 @@
+/*
+    GNOME Shell integration for Chrome
+    Copyright (C) 2016  Yuri Konotopov <ykonotopov gmail com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+ */
+
+/* global chrome, COMPAT */
+
+COMPAT.ON_INSTALLED                            = true;
+COMPAT.ON_STARTUP                              = true;
+COMPAT.PERMISSIONS_CONTAINS            = true;
+COMPAT.SYNC_STORAGE                            = (!COMPAT.IS_OPERA || false);
+COMPAT.NOTIFICATIONS_BUTTONS   = (!COMPAT.IS_OPERA && !COMPAT.IS_FIREFOX || false);
+
+if (typeof (chrome.runtime.onStartup) === 'undefined')
+{
+       chrome.runtime.onStartup = {
+               addListener: function() { }
+       };
+       COMPAT.ON_STARTUP = false;
+}
+
+if(typeof(chrome.runtime.onInstalled) === 'undefined')
+{
+       chrome.runtime.onInstalled = {
+               addListener: function() { }
+       };
+       COMPAT.ON_INSTALLED = false;
+}
+
+if(typeof(chrome.runtime.onMessageExternal) === 'undefined')
+{
+       chrome.runtime.onMessageExternal = {
+               addListener: chrome.runtime.onMessage.addListener
+       };
+}
+
+if(typeof(chrome.permissions) === 'undefined')
+{
+       chrome.permissions = {
+               contains: function(permissions, callback) {
+                       callback(false);
+               }
+       };
+       COMPAT.PERMISSIONS_CONTAINS = false;
+}
+
+if(typeof(chrome.storage.sync) === 'undefined')
+{
+       chrome.storage.sync = chrome.storage.local;
+       COMPAT.SYNC_STORAGE = false;
+}
diff --git a/extension/include/compat-content-script.js b/extension/include/compat-content-script.js
new file mode 100644
index 0000000..96900b9
--- /dev/null
+++ b/extension/include/compat-content-script.js
@@ -0,0 +1,48 @@
+/*
+    GNOME Shell integration for Chrome
+    Copyright (C) 2016  Yuri Konotopov <ykonotopov gmail com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+ */
+
+if(COMPAT.IS_FIREFOX)
+{
+       (function() {
+               // Define the API subset provided to the webpage
+               var externalMessaging = {
+                       runtime: {
+                               sendMessage: function (extensionId, message, options, responseCallback) {
+                                       console.log('In sendMessage');
+                                       if(extensionId !== chrome.i18n.getMessage('@@extension_id'))
+                                       {
+                                               console.error('Wrong extension id provided.')
+                                               return;
+                                       }
+
+                                       if(typeof(options) === 'function')
+                                       {
+                                               responseCallback = options;
+                                               options = undefined;
+                                       }
+
+                                       chrome.runtime.sendMessage(extensionId, message, options)
+                                               .then(result => {
+                                                       responseCallback(cloneInto(result, window));
+                                               })
+                                               .catch(err => {
+                                                       console.error("firefox-external-messaging: 
runtime.sendMessage error", err);
+                                               });
+                               }
+                       }
+               };
+
+               // Inject the API in the webpage wrapped by this content script
+               // (exposed as `chrome.runtime.sendMessage({anyProp: "anyValue"}).then(reply => ..., err => 
...)`)
+               window.wrappedJSObject.chrome = cloneInto(externalMessaging, window, {
+                       cloneFunctions: true,
+               });
+       })();
+}
diff --git a/extension/include/constants.js b/extension/include/constants.js
index 96ae2ab..94b672e 100644
--- a/extension/include/constants.js
+++ b/extension/include/constants.js
@@ -11,7 +11,10 @@
 GS_CHROME_ID                           = chrome.i18n.getMessage('@@extension_id');
 PLATFORMS_WHITELIST                    = ["linux", "openbsd"];
 
-IS_OPERA                               = navigator.userAgent.indexOf(' OPR/') >= 0;
+COMPAT = {
+       IS_FIREFOX:      (typeof(InstallTrigger) !== 'undefined'),
+       IS_OPERA:        navigator.userAgent.indexOf(' OPR/') >= 0
+};
 
 NOTIFICATION_SYNC_FAILED               = 'gs-chrome-sync-fail';
 NOTIFICATION_UPDATE_AVAILABLE          = 'gs-chrome-update';
diff --git a/extension/include/notifications.js b/extension/include/notifications.js
index 2c12141..08750fe 100644
--- a/extension/include/notifications.js
+++ b/extension/include/notifications.js
@@ -11,9 +11,11 @@
 GSC.notifications = (function($) {
        var browser = (function() {
                function init() {
-                       chrome.runtime.onStartup.addListener(function() {
-                               // Do nothing. We just need this callback to restore notifications
-                       });
+                       if(COMPAT.ON_STARTUP) {
+                               chrome.runtime.onStartup.addListener(function() {
+                                       // Do nothing. We just need this callback to restore notifications
+                               });
+                       }
 
                        chrome.notifications.onClosed.addListener(function (notificationId, byUser) {
                                if (!byUser)
@@ -62,9 +64,13 @@ GSC.notifications = (function($) {
 
                function _create(name, options, callback)
                {
-                       if(IS_OPERA && options.buttons)
+                       if(!COMPAT.NOTIFICATIONS_BUTTONS && options.buttons)
                        {
                                delete options.buttons;
+                       }
+
+                       if(COMPAT.IS_OPERA)
+                       {
                                if(options.type === chrome.notifications.TemplateType.LIST)
                                {
                                        var items = [];
diff --git a/extension/include/sync.js b/extension/include/sync.js
index 80be629..fe708fc 100644
--- a/extension/include/sync.js
+++ b/extension/include/sync.js
@@ -16,8 +16,7 @@ GSC.sync = (function($) {
         * Initialization rutines.
         */
        function init() {
-               // Opera do not supports remote storage yet.
-               if(IS_OPERA)
+               if(!COMPAT.SYNC_STORAGE)
                {
                        return;
                }
@@ -281,7 +280,7 @@ GSC.sync = (function($) {
         */
        function onExtensionChanged(request)
        {
-               if(IS_OPERA)
+               if(!COMPAT.SYNC_STORAGE)
                {
                        return;
                }
@@ -301,7 +300,7 @@ GSC.sync = (function($) {
         */
        function onSyncFromRemote(remoteExtensions)
        {
-               if(IS_OPERA)
+               if(!COMPAT.SYNC_STORAGE)
                {
                        return;
                }
diff --git a/extension/manifest.firefox.json b/extension/manifest.firefox.json
new file mode 100644
index 0000000..94f816d
--- /dev/null
+++ b/extension/manifest.firefox.json
@@ -0,0 +1,16 @@
+{
+  "applications": {
+    "gecko": {
+      "id": "chrome-gnome-shell gnome org",
+      "strict_min_version": "50.0"
+    }
+  },
+  "permissions": [
+    "alarms",
+    "nativeMessaging",
+    "notifications",
+    "storage",
+    "tabs",
+    "https://extensions.gnome.org/";
+  ]
+}
diff --git a/extension/manifest.json b/extension/manifest.json
index 946d713..128b9a6 100644
--- a/extension/manifest.json
+++ b/extension/manifest.json
@@ -28,6 +28,7 @@
       "run_at": "document_start",
       "js": [
            "include/constants.js",
+           "include/compat-content-script.js",
            "content-script-start.js"
       ]
     },
diff --git a/extension/options.html b/extension/options.html
index 44b06ba..d84bc5a 100644
--- a/extension/options.html
+++ b/extension/options.html
@@ -8,6 +8,7 @@
                <script type="text/javascript" src="include/external/tabby-10.1.0.js"></script>
                <script type="text/javascript" src="include/i18n.js"></script>
                <script type="text/javascript" src="include/constants.js"></script>
+               <script type="text/javascript" src="include/compat-common.js"></script>
                <script type="text/javascript" src="include/gsc.js"></script>
                <script type="text/javascript" src="include/sync.js"></script>
        </head>
diff --git a/extension/options.js b/extension/options.js
index 316e6d1..b1d93ca 100644
--- a/extension/options.js
+++ b/extension/options.js
@@ -100,7 +100,7 @@ function restore_options()
                setNetworkErrors(result);
        });
 
-       if(!IS_OPERA)
+       if(COMPAT.SYNC_STORAGE)
        {
                updateSynchronizationStatus();
                chrome.storage.local.get(DEFAULT_LOCAL_OPTIONS, function (items) {
@@ -112,6 +112,21 @@ function restore_options()
                $('a[data-i18n="synchronization"]').parent().remove();
                $('#synchronize_extensions_yes').closest('dl').hide();
        }
+
+       if(COMPAT.IS_FIREFOX)
+       {
+               $('dialog').hide();
+       }
+
+       if(!COMPAT.PERMISSIONS_CONTAINS)
+       {
+               $('#show_network_errors_yes').parents('dl:first').hide();
+       }
+
+       if(!COMPAT.ON_INSTALLED)
+       {
+               $('#show_release_notes_yes').parents('dl:first').hide();
+       }
 }
 
 function retrieveUpdateTimes()


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