Weblinks API for embedded scenario using Gerrit.Nav interface

Gerrit.Nav.setup() now takes a weblinks generator function as a third
parameter. Here's the function signature:

``` js
Gerrit.Nav.setup(navigate, generateUrl, generateWeblinks)
```

Weblinks generator function takes single payload parameter with
`type` property that determines which part of the UI is the consumer of
the weblinks. `type` property can be one of `file`, `change`, or
`patchset`.

For `file` type, payload will also contain string properties:
`repo`, `commit`, `file`.

For `pachset` type, payload will also contain string properties:
`repo`, `commit`.

For `change` type, payload will also contain string properties:
`repo`, `commit`.

If server provides weblinks, those will be passed as `options.weblinks`
property on the main payload object.

Change-Id: I0d9de3a295435304e2b6aad551112440075cf098
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
index 8f255f8..e5f525e 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
@@ -20,8 +20,10 @@
 <link rel="import" href="../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html">
 <link rel="import" href="../../../behaviors/rest-client-behavior/rest-client-behavior.html">
 <link rel="import" href="../../../bower_components/iron-dropdown/iron-dropdown.html">
+<link rel="import" href="../../../styles/shared-styles.html">
 <link rel="import" href="../../core/gr-navigation/gr-navigation.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
+<link rel="import" href="../../shared/gr-count-string-formatter/gr-count-string-formatter.html">
 <link rel="import" href="../../shared/gr-dropdown-list/gr-dropdown-list.html">
 <link rel="import" href="../../shared/gr-fixed-panel/gr-fixed-panel.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
@@ -32,7 +34,6 @@
 <link rel="import" href="../gr-diff-preferences/gr-diff-preferences.html">
 <link rel="import" href="../gr-diff/gr-diff.html">
 <link rel="import" href="../gr-patch-range-select/gr-patch-range-select.html">
-<link rel="import" href="../../../styles/shared-styles.html">
 
 <dom-module id="gr-diff-view">
   <template>
@@ -293,6 +294,7 @@
         is-image-diff="{{_isImageDiff}}"
         files-weblinks="{{_filesWeblinks}}"
         change-num="[[_changeNum]]"
+        commit-range="[[_commitRange]]"
         patch-range="[[_patchRange]]"
         path="[[_path]]"
         prefs="[[_prefs]]"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index f0b70c1..8c2954b 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -63,6 +63,8 @@
       },
       /** @type {?} */
       _patchRange: Object,
+      /** @type {?} */
+      _commitRange: Object,
       /**
        * @type {{
        *  subject: string,
@@ -208,6 +210,7 @@
     _getChangeDetail(changeNum) {
       return this.$.restAPI.getDiffChangeDetail(changeNum).then(change => {
         this._change = change;
+        return change;
       });
     },
 
@@ -531,7 +534,20 @@
         this._userPrefs = prefs;
       }));
 
-      promises.push(this._getChangeDetail(this._changeNum));
+      promises.push(this._getChangeDetail(this._changeNum).then(change => {
+        let commit;
+        let baseCommit;
+        for (const k in change.revisions) {
+          if (!change.revisions.hasOwnProperty(k)) continue;
+          const patchNum = change.revisions[k]._number.toString();
+          if (patchNum === this._patchRange.patchNum) {
+            commit = k;
+          } else if (patchNum === this._patchRange.basePatchNum) {
+            baseCommit = k;
+          }
+        }
+        this._commitRange = {commit, baseCommit};
+      }));
 
       promises.push(this._loadComments());
 
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
index ccf986e..8fe8c40 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
@@ -51,6 +51,7 @@
       sandbox = sinon.sandbox.create();
 
       stub('gr-rest-api-interface', {
+        getConfig() { return Promise.resolve({change: {}}); },
         getLoggedIn() { return Promise.resolve(false); },
         getProjectConfig() { return Promise.resolve({}); },
         getDiffChangeDetail() { return Promise.resolve(null); },
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index 21598a2..532b928 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -15,8 +15,8 @@
 -->
 
 <link rel="import" href="../../../bower_components/polymer/polymer.html">
-
 <link rel="import" href="../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html">
+<link rel="import" href="../../../styles/shared-styles.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 <link rel="import" href="../gr-diff-builder/gr-diff-builder.html">
@@ -24,7 +24,6 @@
 <link rel="import" href="../gr-diff-highlight/gr-diff-highlight.html">
 <link rel="import" href="../gr-diff-selection/gr-diff-selection.html">
 <link rel="import" href="../gr-syntax-themes/gr-theme-default.html">
-<link rel="import" href="../../../styles/shared-styles.html">
 
 <script src="../../../scripts/hiddenscroll.js"></script>
 
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
index 6300c49..5f3269a 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -73,6 +73,7 @@
         computed: '_computeIsImageDiff(_diff)',
         notify: true,
       },
+      commitRange: Object,
       filesWeblinks: {
         type: Object,
         value() { return {}; },
@@ -636,9 +637,17 @@
           this.patchRange.patchNum,
           this.path,
           this._handleGetDiffError.bind(this)).then(diff => {
+            if (!this.commitRange) {
+              this.filesWeblinks = {};
+              return diff;
+            }
             this.filesWeblinks = {
-              meta_a: diff && diff.meta_a && diff.meta_a.web_links,
-              meta_b: diff && diff.meta_b && diff.meta_b.web_links,
+              meta_a: Gerrit.Nav.getFileWebLinks(
+                  this.projectName, this.commitRange.commit, this.path,
+                  {weblinks: diff && diff.meta_a && diff.meta_a.web_links}),
+              meta_b: Gerrit.Nav.getFileWebLinks(
+                  this.projectName, this.commitRange.baseCommit, this.path,
+                  {weblinks: diff && diff.meta_b && diff.meta_b.web_links}),
             };
             return diff;
           });
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
index ea872a0..50a5b1e 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
@@ -189,23 +189,18 @@
             element.$$('.diffContainer').classList.contains('displayLine'));
       });
 
-      test('loads files weblinks', done => {
-        sandbox.stub(element.$.restAPI, 'getDiff').returns(
-            Promise.resolve({
-              meta_a: {
-                web_links: 'foo',
-              },
-              meta_b: {
-                web_links: 'bar',
-              },
-            }));
+      test('loads files weblinks', () => {
+        const weblinksStub = sandbox.stub(Gerrit.Nav, '_generateWeblinks')
+            .returns([{name: 'stubb', url: '#s'}]);
+        sandbox.stub(element.$.restAPI, 'getDiff').returns(Promise.resolve({}));
+        element.commitRange = {};
         element.patchRange = {};
-        element._getDiff().then(() => {
+        return element._getDiff().then(() => {
+          assert.isTrue(weblinksStub.called);
           assert.deepEqual(element.filesWeblinks, {
-            meta_a: 'foo',
-            meta_b: 'bar',
+            meta_a: [{name: 'stubb', url: '#s'}],
+            meta_b: [{name: 'stubb', url: '#s'}],
           });
-          done();
         });
       });