Merge "Merge doc and change searches."
diff --git a/Documentation/rest-api-config.txt b/Documentation/rest-api-config.txt
index b1b795c..3a64dc0 100644
--- a/Documentation/rest-api-config.txt
+++ b/Documentation/rest-api-config.txt
@@ -115,6 +115,7 @@
     "gerrit": {
       "all_projects": "All-Projects",
       "all_users": "All-Users"
+      "doc_search": true
     },
     "sshd": {},
     "suggest": {
@@ -1189,6 +1190,8 @@
 |`all_users_name`    ||
 Name of the link:config-gerrit.html#gerrit.allUsers[project in which
 meta data of all users is stored].
+|`doc_search`        ||
+Whether documentation search is available.
 |`doc_url`           |optional|
 Custom base URL where Gerrit server documentation is located.
 (Documentation may still be available at /Documentation relative to the
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
index 28e0d24..b6cd45f 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
@@ -49,6 +49,7 @@
   public static final String ADMIN_CREATE_PROJECT = "/admin/create-project/";
   public static final String ADMIN_PLUGINS = "/admin/plugins/";
   public static final String MY_GROUPS = "/groups/self";
+  public static final String DOCUMENTATION = "/Documentation/";
 
   public static String toChange(final ChangeInfo c) {
     return toChange(c.getId());
@@ -140,6 +141,10 @@
     return SETTINGS_EXTENSION + pluginName + "/" + path;
   }
 
+  public static String toDocumentationQuery(String query) {
+    return DOCUMENTATION + KeyUtil.encode(query);
+  }
+
   private static String status(Status status) {
     switch (status) {
       case ABANDONED:
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GerritInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GerritInfo.java
index 55ef892..750412d 100644
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GerritInfo.java
+++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GerritInfo.java
@@ -36,6 +36,7 @@
 
   public final native String allProjects() /*-{ return this.all_projects; }-*/;
   public final native String allUsers() /*-{ return this.all_users; }-*/;
+  public final native boolean docSearch() /*-{ return this.doc_search; }-*/;
   public final native String docUrl() /*-{ return this.doc_url; }-*/;
   public final native boolean editGpgKeys() /*-{ return this.edit_gpg_keys || false; }-*/;
   public final native String reportBugUrl() /*-{ return this.report_bug_url; }-*/;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index 3b58ac0..139b9c0 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -118,6 +118,7 @@
   private static AccountPreferencesInfo myPrefs;
   private static UrlAliasMatcher urlAliasMatcher;
   private static boolean hasDocumentation;
+  private static boolean docSearch;
   private static String docUrl;
   private static HostPageData.Theme myTheme;
   private static String defaultScreenToken;
@@ -487,6 +488,7 @@
           hasDocumentation = true;
           docUrl = du;
         }
+        docSearch = info.gerrit().docSearch();
       }
     }));
     HostPageDataService hpd = GWT.create(HostPageDataService.class);
@@ -918,6 +920,10 @@
     urlAliasMatcher.updateUserAliases(myPrefs.urlAliases());
   }
 
+  public static boolean hasDocSearch() {
+    return docSearch;
+  }
+
   private static void getDocIndex(final AsyncCallback<DocInfo> cb) {
     RequestBuilder req =
         new RequestBuilder(RequestBuilder.HEAD, GWT.getHostPageBaseURL()
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
index 269999c..6802a0d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
@@ -126,4 +126,7 @@
   String stringListPanelDelete();
   String stringListPanelUp();
   String stringListPanelDown();
+
+  String searchDropdownChanges();
+  String searchDropdownDoc();
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
index fb74506..1337b31 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
@@ -109,3 +109,6 @@
 stringListPanelDelete = Delete
 stringListPanelUp = Up
 stringListPanelDown = Down
+
+searchDropdownChanges = Changes
+searchDropdownDoc = Documentation
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
index 45b1d52..83a187b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
@@ -27,6 +27,7 @@
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.SuggestBox;
 import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
@@ -34,6 +35,7 @@
 
 class SearchPanel extends Composite {
   private final HintTextBox searchBox;
+  private final ListBox dropdown;
   private HandlerRegistration regFocus;
 
   SearchPanel() {
@@ -54,6 +56,18 @@
       }
     });
 
+    if (Gerrit.hasDocSearch()) {
+      dropdown = new ListBox();
+      dropdown.setStyleName("searchDropdown");
+      dropdown.addItem(Gerrit.C.searchDropdownChanges());
+      dropdown.addItem(Gerrit.C.searchDropdownDoc());
+      dropdown.setVisibleItemCount(1);
+      dropdown.setSelectedIndex(0);
+    } else {
+      // Doc search is NOT available.
+      dropdown = null;
+    }
+
     final SuggestBox suggestBox =
         new SuggestBox(new SearchSuggestOracle(), searchBox, suggestionDisplay);
     searchBox.setStyleName("searchTextBox");
@@ -70,6 +84,9 @@
     });
 
     body.add(suggestBox);
+    if (dropdown != null) {
+      body.add(dropdown);
+    }
     body.add(searchButton);
   }
 
@@ -110,14 +127,23 @@
 
     searchBox.setFocus(false);
 
-    if (query.matches("^[1-9][0-9]*$")) {
-      Gerrit.display(PageLinks.toChange(Change.Id.parse(query)));
+    if (dropdown != null
+        && dropdown.getSelectedValue().equals(Gerrit.C.searchDropdownDoc())) {
+      // doc
+      Gerrit.display(PageLinks.toDocumentationQuery(query));
     } else {
-      Gerrit.display(PageLinks.toChangeQuery(query), QueryScreen.forQuery(query));
+      // changes
+      if (query.matches("^[1-9][0-9]*$")) {
+        Gerrit.display(PageLinks.toChange(Change.Id.parse(query)));
+      } else {
+        Gerrit.display(
+            PageLinks.toChangeQuery(query), QueryScreen.forQuery(query));
+      }
     }
   }
 
-  private static class MySuggestionDisplay extends SuggestBox.DefaultSuggestionDisplay {
+  private static class MySuggestionDisplay
+      extends SuggestBox.DefaultSuggestionDisplay {
     private boolean isSuggestionSelected;
 
     private MySuggestionDisplay() {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index 0987e83..3c9a8b9 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -307,7 +307,15 @@
 }
 .searchPanel .searchTextBox {
   font-size: 9pt;
-  margin: 5.286px 3px 0 0;
+  margin: 8.286px 3px 0 0;
+}
+.searchPanel .searchDropdown {
+  font-size: 8pt;
+  border: 2px solid;
+  border-color: rgba(0, 0, 0, 0.15);
+  height: 16px;
+  border-radius: 2px;
+  box-sizing: content-box;
 }
 .searchPanel .searchButton {
   text-align: center;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
index 9eca842..e5ac370 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
@@ -35,6 +35,7 @@
 import com.google.gerrit.server.change.ArchiveFormat;
 import com.google.gerrit.server.change.GetArchive;
 import com.google.gerrit.server.change.Submit;
+import com.google.gerrit.server.documentation.QueryDocumentationExecutor;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.lib.Config;
@@ -64,6 +65,7 @@
   private final GitwebConfig gitwebConfig;
   private final DynamicItem<AvatarProvider> avatar;
   private final boolean enableSignedPush;
+  private final QueryDocumentationExecutor docSearcher;
 
   @Inject
   public GetServerInfo(
@@ -79,7 +81,8 @@
       @AnonymousCowardName String anonymousCowardName,
       GitwebConfig gitwebConfig,
       DynamicItem<AvatarProvider> avatar,
-      @EnableSignedPush boolean enableSignedPush) {
+      @EnableSignedPush boolean enableSignedPush,
+      QueryDocumentationExecutor docSearcher) {
     this.config = config;
     this.authConfig = authConfig;
     this.realm = realm;
@@ -93,6 +96,7 @@
     this.gitwebConfig = gitwebConfig;
     this.avatar = avatar;
     this.enableSignedPush = enableSignedPush;
+    this.docSearcher = docSearcher;
   }
 
   @Override
@@ -238,6 +242,7 @@
     info.reportBugUrl = cfg.getString("gerrit", null, "reportBugUrl");
     info.reportBugText = cfg.getString("gerrit", null, "reportBugText");
     info.docUrl = getDocUrl(cfg);
+    info.docSearch = docSearcher.isAvailable();
     info.editGpgKeys = toBoolean(enableSignedPush
         && cfg.getBoolean("gerrit", null, "editGpgKeys", true));
     return info;
@@ -366,10 +371,11 @@
   public static class GerritInfo {
     public String allProjects;
     public String allUsers;
+    public Boolean docSearch;
     public String docUrl;
+    public Boolean editGpgKeys;
     public String reportBugUrl;
     public String reportBugText;
-    public Boolean editGpgKeys;
   }
 
   public static class GitwebInfo {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/documentation/QueryDocumentationExecutor.java b/gerrit-server/src/main/java/com/google/gerrit/server/documentation/QueryDocumentationExecutor.java
index 446013e..438795f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/documentation/QueryDocumentationExecutor.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/documentation/QueryDocumentationExecutor.java
@@ -74,7 +74,7 @@
   }
 
   public List<DocResult> doQuery(String q) throws DocQueryException {
-    if (parser == null || searcher == null) {
+    if (!isAvailable()) {
       throw new DocQueryException("Documentation search not available");
     }
     try {
@@ -123,6 +123,10 @@
     return dir;
   }
 
+  public boolean isAvailable() {
+    return parser != null && searcher != null;
+  }
+
   @SuppressWarnings("serial")
   public static class DocQueryException extends Exception {
     DocQueryException() {