Merge branch 'stable-3.1' into stable-3.2

* stable-3.1:
  Fix inline display to work with shadow dom
  Remove GWT UI
  Adapt to Gerrit 3.1 API

Change-Id: I028fabacdccbc98075ae0f3d7db71dcf23938a83
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/GetConfig.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/GetConfig.java
index 4ddd017..dc3e17d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/GetConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/GetConfig.java
@@ -17,6 +17,7 @@
 import com.google.common.base.MoreObjects;
 import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl;
 import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.config.PluginConfig;
@@ -40,7 +41,7 @@
   }
 
   @Override
-  public ConfigInfo apply(ConfigResource resource) {
+  public Response<ConfigInfo> apply(ConfigResource resource) {
     ConfigInfo info = new ConfigInfo();
     info.defaultProject = MoreObjects.firstNonNull(cfg.getString("defaultProject"), "All-Projects");
     info.linkDecoration = cfg.getEnum("linkDecoration", LinkDecoration.INLINE);
@@ -67,7 +68,7 @@
       info.uploadUrl = cfg.getString("uploadUrl");
     }
 
-    return info;
+    return Response.ok(info);
   }
 
   /**
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/GetPreference.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/GetPreference.java
index e69b27d..a7bf3e0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/GetPreference.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/GetPreference.java
@@ -19,6 +19,8 @@
 import com.google.common.base.MoreObjects;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.Response;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountResource;
@@ -58,14 +60,19 @@
   }
 
   @Override
-  public ConfigInfo apply(AccountResource rsrc) throws AuthException, PermissionBackendException {
+  public Response<ConfigInfo> apply(AccountResource rsrc) throws PermissionBackendException, RestApiException {
     if (self.get() != rsrc.getUser()) {
       permissionBackend.currentUser().check(ADMINISTRATE_SERVER);
     }
 
     String username = self.get().getUserName().get();
 
-    ConfigInfo globalCfg = getConfig.get().apply(new ConfigResource());
+    ConfigInfo globalCfg;
+    try {
+      globalCfg = getConfig.get().apply(new ConfigResource()).value();
+    } catch (Exception e) {
+      throw new RestApiException("Failed to get global config.");
+    }
 
     Config db = projectCache.getAllProjects().getConfig(pluginName + ".config").get();
     ConfigInfo info = new ConfigInfo();
@@ -93,6 +100,6 @@
 
     info.pattern = globalCfg.pattern;
 
-    return info;
+    return Response.ok(info);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/HttpModule.java
index 627cfd8..f7960e8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/HttpModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/HttpModule.java
@@ -39,10 +39,6 @@
       serveRegex("^" + ImageServlet.PATH_PREFIX + "(.+)?$").with(ImageServlet.class);
     }
 
-    // GWT only
-    DynamicSet.bind(binder(), WebUiPlugin.class).toInstance(new JavaScriptPlugin("imagare.js"));
-
-    // Polymer only
     DynamicSet.bind(binder(), WebUiPlugin.class).toInstance(new JavaScriptPlugin("imagare.html"));
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/ImageResource.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/ImageResource.java
index d57d42f..3551a9e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/ImageResource.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/ImageResource.java
@@ -14,31 +14,31 @@
 
 package com.googlesource.gerrit.plugins.imagare;
 
+import com.google.gerrit.entities.BranchNameKey;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.restapi.RestResource;
 import com.google.gerrit.extensions.restapi.RestView;
-import com.google.gerrit.reviewdb.client.Branch;
-import com.google.gerrit.reviewdb.client.Project;
 import com.google.inject.TypeLiteral;
 
 public class ImageResource implements RestResource {
   public static final TypeLiteral<RestView<ImageResource>> IMAGE_KIND =
       new TypeLiteral<RestView<ImageResource>>() {};
 
-  private Branch.NameKey branchName;
+  private BranchNameKey branchName;
 
-  ImageResource(Branch.NameKey branchName) {
+  ImageResource(BranchNameKey branchName) {
     this.branchName = branchName;
   }
 
   public Project.NameKey getProject() {
-    return branchName.getParentKey();
+    return branchName.project();
   }
 
   public String getRef() {
-    return branchName.get();
+    return branchName.branch();
   }
 
-  public Branch.NameKey getBranchKey() {
+  public BranchNameKey getBranchKey() {
     return branchName;
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/ImageServlet.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/ImageServlet.java
index 9c47679..13d4ab0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/ImageServlet.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/ImageServlet.java
@@ -20,11 +20,11 @@
 import com.google.common.base.CharMatcher;
 import com.google.common.hash.Hashing;
 import com.google.common.net.HttpHeaders;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
-import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.mime.FileTypeRegistry;
@@ -118,7 +118,11 @@
       ProjectState projectState = projectCache.get(key.project);
       String rev = key.revision;
       if (rev == null || Constants.HEAD.equals(rev)) {
-        rev = getHead.get().apply(new ProjectResource(projectState, self.get()));
+        try {
+          rev = getHead.get().apply(new ProjectResource(projectState, self.get())).value();
+        } catch (Exception e) {
+          throw new ResourceNotFoundException(String.format("Could not get head of project %s.", key.project));
+        }
       } else {
         if (!ObjectId.isId(rev)) {
           if (!rev.startsWith(Constants.R_REFS)) {
@@ -199,7 +203,6 @@
       }
     } catch (RepositoryNotFoundException
         | ResourceNotFoundException
-        | AuthException
         | RevisionSyntaxException
         | PermissionBackendException e) {
       notFound(res);
@@ -298,7 +301,7 @@
     }
 
     private ResourceKey(String p, String f, String r) {
-      project = new Project.NameKey(p);
+      project = Project.nameKey(p);
       file = f;
       revision = r;
     }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/ImagesCollection.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/ImagesCollection.java
index 92a8493..8070266 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/ImagesCollection.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/ImagesCollection.java
@@ -14,12 +14,12 @@
 
 package com.googlesource.gerrit.plugins.imagare;
 
+import com.google.gerrit.entities.BranchNameKey;
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.restapi.ChildCollection;
 import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestView;
-import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.permissions.RefPermission;
 import com.google.gerrit.server.project.ProjectResource;
@@ -48,7 +48,7 @@
 
   @Override
   public ImageResource parse(ProjectResource parent, IdString id) throws ResourceNotFoundException {
-    Branch.NameKey branchName = new Branch.NameKey(parent.getNameKey(), id.get());
+    BranchNameKey branchName = BranchNameKey.create(parent.getNameKey(), id.get());
     if (permissionBackend.user(parent.getUser()).ref(branchName).testOrFalse(RefPermission.READ)) {
       return new ImageResource(branchName);
     }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/PostImage.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/PostImage.java
index 0a330f1..5fe103a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/PostImage.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/PostImage.java
@@ -14,6 +14,8 @@
 
 package com.googlesource.gerrit.plugins.imagare;
 
+import com.google.gerrit.entities.BranchNameKey;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -23,8 +25,6 @@
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
-import com.google.gerrit.reviewdb.client.Branch;
-import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.CanonicalWebUrl;
@@ -186,7 +186,7 @@
           createRefControl.checkCreateRef(
               self,
               repo,
-              new Branch.NameKey(ps.getProject().getNameKey(), ref),
+              BranchNameKey.create(ps.getProject().getNameKey(), ref),
               rw.parseCommit(commitId));
         } catch (AuthException e) {
           throw new AuthException(
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/PutConfig.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/PutConfig.java
index 8443094..99ad85d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/PutConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/PutConfig.java
@@ -16,13 +16,13 @@
 
 import com.google.common.base.Strings;
 import com.google.gerrit.common.data.GlobalCapability;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.annotations.CapabilityScope;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
-import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.gerrit.server.config.SitePaths;
@@ -71,7 +71,7 @@
     cfg.load();
 
     if (input.defaultProject != null) {
-      if (projectCache.get(new Project.NameKey(input.defaultProject)) == null) {
+      if (projectCache.get(Project.nameKey(input.defaultProject)) == null) {
         throw new UnprocessableEntityException(
             "project '" + input.defaultProject + "' does not exist");
       }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/PutPreference.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/PutPreference.java
index ffd00d4..a882042 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/PutPreference.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/PutPreference.java
@@ -21,12 +21,12 @@
 import static com.googlesource.gerrit.plugins.imagare.GetPreference.PREFERENCE;
 
 import com.google.common.base.Strings;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
-import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountResource;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
@@ -81,7 +81,7 @@
 
     String defaultProject = db.getString(PREFERENCE, username, KEY_DEFAULT_PROJECT);
     if (Strings.emptyToNull(input.defaultProject) != null) {
-      if (projectCache.get(new Project.NameKey(input.defaultProject)) == null) {
+      if (projectCache.get(Project.nameKey(input.defaultProject)) == null) {
         throw new UnprocessableEntityException(
             "project '" + input.defaultProject + "' does not exist");
       }
diff --git a/src/main/resources/static/gr-imagare-inline.js b/src/main/resources/static/gr-imagare-inline.js
index 3001252..903b53e 100644
--- a/src/main/resources/static/gr-imagare-inline.js
+++ b/src/main/resources/static/gr-imagare-inline.js
@@ -67,7 +67,10 @@
         });
 
         this._messageAddedObserver.observe(
-          document.getElementsByTagName('gr-messages-list')[0],
+          // TODO(Thomas): The util methods were removed in change 270988, which
+          // will break this code in newer Gerrit versions (3.3+). At this point
+          // the plugin should implement the querySelector(All)-methods itself.
+          util.querySelector(document.body, 'gr-messages-list'),
           {
             childList: true,
           });
@@ -128,20 +131,20 @@
     },
 
     _getMessages() {
-      let messageList = document.getElementsByTagName('gr-messages-list')[0];
+      let messageList = util.querySelector(document.body, 'gr-messages-list');
       if (messageList) {
-        return messageList.getElementsByTagName('gr-message');
+        return util.querySelectorAll(messageList, 'gr-message');
       }
     },
 
     _getLinksFromMessage(message) {
       let links = [];
-      let linkedTexts = message.getElementsByTagName('gr-linked-text');
+      let linkedTexts = util.querySelectorAll(message, 'gr-linked-text');
       for (const e of linkedTexts) {
-        let aTags = e.getElementsByTagName('a');
+        let aTags = util.querySelectorAll(e, 'a');
         if (aTags && aTags.length > 0){
           for (const a of aTags){
-            if (a.getElementsByTagName('img').length > 0) {
+            if (util.querySelectorAll(a, 'img').length > 0) {
               continue;
             }
             if (!a.href.match(this._pattern)) {
diff --git a/src/main/resources/static/imagare.html b/src/main/resources/static/imagare.html
index 2d2077d..7e3ee3b 100644
--- a/src/main/resources/static/imagare.html
+++ b/src/main/resources/static/imagare.html
@@ -23,8 +23,6 @@
 <dom-module id="imagare">
   <script>
     Gerrit.install(plugin => {
-      if (!window.Polymer) { return; }
-
       plugin.restApi('/config/server/').get('imagare~config').then(config => {
         if (config && config.enable_image_server) {
           plugin.screen('upload', 'gr-imagare-upload');
diff --git a/src/main/resources/static/imagare.js b/src/main/resources/static/imagare.js
deleted file mode 100644
index 779f1b5..0000000
--- a/src/main/resources/static/imagare.js
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-Gerrit.install(function(self) {
-
-    if (window.Polymer) { return; }
-
-    // The code below is only used by the GWT-UI
-
-    function onComment(e) {
-      var prefs = getPrefsFromCookie();
-      if (prefs !== null) {
-        convertImageLinks(getLinks(e), prefs);
-      } else {
-        Gerrit.get('/accounts/self/' + self.getPluginName() + '~preference', function(prefs) {
-          storePrefsInCookie(prefs);
-          convertImageLinks(getLinks(e), prefs);
-        });
-      }
-    }
-
-    function getLinks(e) {
-      return e.getElementsByTagName("a");
-    }
-
-    function storePrefsInCookie(prefs) {
-      var date = new Date();
-      date.setTime(date.getTime() + (1 * 24 * 60 * 60 * 1000)); // 1 day
-      document.cookie = getCookieName()
-          + "="
-          + JSON.stringify(prefs)
-          + "; expires=" + date.toGMTString()
-          + "; path=/";
-    }
-
-    function getPrefsFromCookie() {
-      var cookie = document.cookie;
-      if (cookie.length > 0) {
-        var cookieName = getCookieName();
-        var start = cookie.indexOf(cookieName + "=");
-        if (start != -1) {
-            start = start + cookieName.length + 1;
-            var end = document.cookie.indexOf(";", start);
-            if (end == -1) {
-                end = document.cookie.length;
-            }
-            return JSON.parse(unescape(document.cookie.substring(start, end)));
-        }
-      }
-      return null;
-    }
-
-    function getCookieName() {
-      return self.getPluginName() + "~prefs";
-    }
-
-    function convertImageLinks(l, prefs) {
-      if (!prefs.pattern) {
-        return;
-      }
-
-      if ('TOOLTIP' === prefs.link_decoration) {
-        addTooltips(l, prefs.pattern);
-      } else if ('INLINE' === prefs.link_decoration) {
-        inlineImages(l, prefs.pattern);
-      }
-    }
-
-    function inlineImages(l, pattern) {
-      for(var i = 0; i < l.length; i++) {
-        if (l[i].href.match(pattern)) {
-          var a = document.createElement('a');
-          a.setAttribute('href', l[i].href);
-          var img = document.createElement('img');
-          img.setAttribute('src', l[i].href);
-          img.setAttribute('style', 'border: 1px solid #B3B2B2;');
-          a.appendChild(img);
-          l[i].parentNode.replaceChild(a, l[i]);
-        }
-      }
-    }
-
-    function addTooltips(pattern) {
-      for(var i = 0; i < l.length; i++) {
-        if (l[i].href.match(pattern)) {
-          l[i].onmouseover = function (evt) {
-            var img = document.createElement('img');
-            img.setAttribute('src', this.href);
-            img.setAttribute('style', 'border: 1px solid #B3B2B2; position: absolute; top: ' + (this.offsetTop + this.offsetHeight) + 'px');
-            this.parentNode.insertBefore(img, this);
-            this.onmouseout = function (evt) {
-              this.parentNode.removeChild(this.previousSibling);
-            }
-          }
-        }
-      }
-    }
-
-    Gerrit.on('comment', onComment);
-  });