Fix copy for safari and also copy on formatted text

Under safari, the `user-select` will not be honored for clipboard,
we have to handle the selection manually

Bug: Issue 11784
Bug: Issue 11649
Change-Id: Ibe3800d6c12983c7450c239153d6eb4b70abfb37
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.html b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.html
index 6469382..27821f1 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.html
@@ -17,6 +17,7 @@
 <link rel="import" href="/bower_components/polymer/polymer.html">
 <link rel="import" href="../../../behaviors/dom-util-behavior/dom-util-behavior.html">
 <link rel="import" href="../../../styles/shared-styles.html">
+<script src="../../../scripts/util.js"></script>
 
 <dom-module id="gr-diff-selection">
   <template>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
index 9cd0527..26104da 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
@@ -161,11 +161,6 @@
     },
 
     _handleCopy(e) {
-      // Let the browser handle the copy event for polymer 2
-      // as selection across shadow DOM will be hard to process
-      // If you remove the following line, please remove it from tests also.
-      if (window.POLYMER2) return;
-
       let commentSelected = false;
       const target = this._getCopyEventTarget(e);
       if (target.type === 'textarea') { return; }
@@ -186,7 +181,21 @@
     },
 
     /**
-     * Get the text of the current window selection. If commentSelected is
+     * For Polymer 2, use shadowRoot.getSelection instead.
+     */
+    _getSelection() {
+      let selection;
+      if (window.POLYMER2) {
+        const diffHost = util.querySelector(document.body, 'gr-diff');
+        selection = diffHost &&
+          diffHost.shadowRoot &&
+          diffHost.shadowRoot.getSelection();
+      }
+      return selection ? selection: window.getSelection();
+    },
+
+    /**
+     * Get the text of the current selection. If commentSelected is
      * true, it returns only the text of comments within the selection.
      * Otherwise it returns the text of the selected diff region.
      *
@@ -195,7 +204,7 @@
      * @return {string} The selected text.
      */
     _getSelectedText(side, commentSelected) {
-      const sel = window.getSelection();
+      const sel = this._getSelection();
       if (sel.rangeCount != 1) {
         return ''; // No multi-select support yet.
       }
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
index a2696c2..0f5c6dd 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
@@ -189,18 +189,12 @@
     });
 
     test('ignores copy for non-content Element', () => {
-      // See _handleCopy for explanation
-      if (window.POLYMER2) return;
-
       sandbox.stub(element, '_getSelectedText');
       emulateCopyOn(element.querySelector('.not-diff-row'));
       assert.isFalse(element._getSelectedText.called);
     });
 
     test('asks for text for left side Elements', () => {
-      // See _handleCopy for explanation
-      if (window.POLYMER2) return;
-
       element._cachedDiffBuilder.getSideByLineEl.returns('left');
       sandbox.stub(element, '_getSelectedText');
       emulateCopyOn(element.querySelector('div.contentText'));
@@ -208,18 +202,12 @@
     });
 
     test('reacts to copy for content Elements', () => {
-      // See _handleCopy for explanation
-      if (window.POLYMER2) return;
-
       sandbox.stub(element, '_getSelectedText');
       emulateCopyOn(element.querySelector('div.contentText'));
       assert.isTrue(element._getSelectedText.called);
     });
 
     test('copy event is prevented for content Elements', () => {
-      // See _handleCopy for explanation
-      if (window.POLYMER2) return;
-
       sandbox.stub(element, '_getSelectedText');
       element._cachedDiffBuilder.getSideByLineEl.returns('left');
       element._getSelectedText.returns('test');
@@ -228,9 +216,6 @@
     });
 
     test('inserts text into clipboard on copy', () => {
-      // See _handleCopy for explanation
-      if (window.POLYMER2) return;
-
       sandbox.stub(element, '_getSelectedText').returns('the text');
       const event = emulateCopyOn(element.querySelector('div.contentText'));
       assert.deepEqual(