Add feature to fix link drag&drop in CC

This change adds an option to fix the drag&drop bug that exists in
CKEditor (https://dev.ckeditor.com/ticket/13569), which is the library
used for the rich text editor in the Community Console.

Fixes: #20
Change-Id: Ic82bf6ee6d583876858f21291723dacb5e74debe
diff --git a/src/_locales/ca/messages.json b/src/_locales/ca/messages.json
index 6a77a77..65a5cdd 100644
--- a/src/_locales/ca/messages.json
+++ b/src/_locales/ca/messages.json
@@ -79,6 +79,10 @@
     "message": "Amaga sempre la barra lateral de l'esquerra a la Consola de la Comunitat.",
     "description": "Feature checkbox in the options page"
   },
+  "options_ccdragndropfix": {
+    "message": "Permet arrossegar adreces d'interès a l'editor de text de la Consola de la Comunitat.",
+    "description": "Feature checkbox in the options page"
+  },
   "options_profileindicator_header": {
     "message": "Punt indicador",
     "description": "Heading for the profile indicator feature options"
diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json
index 3472ee8..5800cf9 100644
--- a/src/_locales/en/messages.json
+++ b/src/_locales/en/messages.json
@@ -83,6 +83,10 @@
     "message": "Always hide the drawer (left column) in the Community Console.",
     "description": "Feature checkbox in the options page"
   },
+  "options_ccdragndropfix": {
+    "message": "Allow to drag and drop bookmarks to the Community Console text editor.",
+    "description": "Feature checkbox in the options page"
+  },
   "options_profileindicator_header": {
     "message": "Indicator dot",
     "description": "Heading for the profile indicator feature options"
diff --git a/src/_locales/es/messages.json b/src/_locales/es/messages.json
index 61156c7..cce5f74 100644
--- a/src/_locales/es/messages.json
+++ b/src/_locales/es/messages.json
@@ -79,6 +79,10 @@
     "message": "Esconde siempre la barra lateral izquierda en la Consola de la Comunidad.",
     "description": "Feature checkbox in the options page"
   },
+  "options_ccdragndropfix": {
+    "message": "Permite arrastrar marcadores al editor de texto de la Consola de la Comunidad.",
+    "description": "Feature checkbox in the options page"
+  },
   "options_profileindicator_header": {
     "message": "Punto indicador",
     "description": "Heading for the profile indicator feature options"
diff --git a/src/common/common.js b/src/common/common.js
index 1a67bca..6bfdf02 100644
--- a/src/common/common.js
+++ b/src/common/common.js
@@ -18,12 +18,14 @@
   'ccdarktheme_mode': 'switch',
   'ccdarktheme_switch_enabled': true,
   'ccforcehidedrawer': false,
+  'ccdragndropfix': false,
 };
 
 const specialOptions = [
   'profileindicatoralt_months',
   'ccdarktheme_mode',
   'ccdarktheme_switch_enabled',
+  'ccdragndropfix',
 ];
 
 const deprecatedOptions = [
@@ -59,3 +61,11 @@
 
   return options;
 }
+
+// This method is based on the fact that when building the extension for Firefox
+// the browser_specific_settings.gecko entry is included.
+function isFirefox() {
+  var manifest = chrome.runtime.getManifest();
+  return manifest.browser_specific_settings !== undefined &&
+      manifest.browser_specific_settings.gecko !== undefined;
+}
diff --git a/src/content_scripts/console_inject.js b/src/content_scripts/console_inject.js
index b5e86f8..4dba614 100644
--- a/src/content_scripts/console_inject.js
+++ b/src/content_scripts/console_inject.js
@@ -32,6 +32,16 @@
   node.appendChild(container);
 }
 
+function applyDragAndDropFix(node) {
+  console.debug('Adding link drag&drop fix to ', node);
+  node.addEventListener('drop', e => {
+    if (e.dataTransfer.types.includes('text/uri-list')) {
+      e.stopImmediatePropagation();
+      console.debug('Stopping link drop event propagation.');
+    }
+  }, true);
+}
+
 function mutationCallback(mutationList, observer) {
   mutationList.forEach((mutation) => {
     if (mutation.type == 'childList') {
@@ -93,6 +103,17 @@
               node.querySelector('.main-card-content').appendChild(container);
             }
           }
+
+          // We target both tags because in different contexts different
+          // elements containing the text editor get added to the DOM structure.
+          // Sometimes it's a EC-MOVABLE-DIALOG which already contains the
+          // EC-RICH-TEXT-EDITOR, and sometimes it's the EC-RICH-TEXT-EDITOR
+          // directly.
+          if (options.ccdragndropfix && ('tagName' in node) &&
+              (node.tagName == 'EC-MOVABLE-DIALOG' ||
+               node.tagName == 'EC-RICH-TEXT-EDITOR')) {
+            applyDragAndDropFix(node);
+          }
         }
       });
     }
diff --git a/src/options.css b/src/options.css
index 2ee205f..e754e14 100644
--- a/src/options.css
+++ b/src/options.css
@@ -20,3 +20,7 @@
   margin-bottom: 16px;
   color: green;
 }
+
+[hidden] {
+  display: none;
+}
diff --git a/src/options.html b/src/options.html
index b571a8c..dc63253 100644
--- a/src/options.html
+++ b/src/options.html
@@ -22,6 +22,7 @@
         <input type="checkbox" id="stickysidebarheaders"> <label for="stickysidebarheaders" data-i18n="stickysidebarheaders"></label><br>
         <input type="checkbox" id="ccdarktheme"> <label for="ccdarktheme" data-i18n="ccdarktheme"></label> <span class="experimental-label" data-i18n="experimental_label"></span><br>
         <input type="checkbox" id="ccforcehidedrawer"> <label for="ccforcehidedrawer" data-i18n="ccforcehidedrawer"></label><br>
+        <span id="dragndrop-wrapper" hidden><input type="checkbox" id="ccdragndropfix"> <label for="ccdragndropfix" data-i18n="ccdragndropfix"></label></span><br>
       </p>
       <h4 data-i18n="profileindicator_header"></h4>
       <p>
diff --git a/src/options.js b/src/options.js
index 4d37a19..742be12 100644
--- a/src/options.js
+++ b/src/options.js
@@ -32,6 +32,10 @@
         case 'ccdarktheme_switch_enabled':
           break;
 
+        case 'ccdragndropfix':
+          options[opt] = document.getElementById(opt).checked || false;
+          break;
+
         default:
           console.warn('Unrecognized option: ' + opt);
           break;
@@ -109,6 +113,18 @@
           case 'ccdarktheme_switch_enabled':
             break;
 
+          // Firefox doesn't support drag and dropping bookmarks into the text
+          // editor while preserving the bookmark title.
+          case 'ccdragndropfix':
+            var showOption = !isFirefox();
+            if (showOption) {
+              document.getElementById('dragndrop-wrapper')
+                  .removeAttribute('hidden');
+
+              if (items[opt] === true)
+                document.getElementById(opt).checked = true;
+            }
+
           default:
             console.warn('Unrecognized option: ' + opt);
             break;