Wait for UI plugins to load
If a screen is registered by a plugin this registration needs to be completed before the dispatcher tries to parse the token. Wait for plugin scripts to finish loading and evaluating. The old method of injecting a script tag was not waiting correctly, especially for GWT based plugins. JavaScript plugins are now required to use Gerrit.install() as this method updates internal Gerrit state tracking the script. Not using install() will eventually cause the UI to report the plugin as failing to load. GWT plugins must override onPluginLoad() not onModuleLoad(). All plugins must recompile with the new glue code, as there is now a handshake between the GWT plugin and the main Gerrit code. All plugins must load within 5 seconds, otherwise the page marks them as failed and reports loading errors. During loading a glass pane is used to prevent the user from interacting with a partial initialized UI. Plugins may be making critical contributions that need to be registered before use. A chunk of the API glue code was moved around to make each JSNI block smaller, and better isolate purpose. Plugin is now declared in its own Java class. Plugin instances are now tracked in the map $wnd.Gerrit.plugins. This allows the main code to later figure out if any instance failed to load. Any loading errors are usually reported on the JavaScript console as script failures, and may include stack traces. Change-Id: Id03581437ae1010cf995ef7ba8626ece37dfc2f4
This commit is contained in:
@@ -22,6 +22,7 @@ import com.google.gerrit.client.account.AccountCapabilities;
|
||||
import com.google.gerrit.client.account.AccountInfo;
|
||||
import com.google.gerrit.client.admin.ProjectScreen;
|
||||
import com.google.gerrit.client.api.ApiGlue;
|
||||
import com.google.gerrit.client.api.PluginLoader;
|
||||
import com.google.gerrit.client.changes.ChangeConstants;
|
||||
import com.google.gerrit.client.changes.ChangeListScreen;
|
||||
import com.google.gerrit.client.config.ConfigServerApi;
|
||||
@@ -49,12 +50,8 @@ import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
|
||||
import com.google.gerrit.reviewdb.client.AuthType;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gwt.aria.client.Roles;
|
||||
import com.google.gwt.core.client.Callback;
|
||||
import com.google.gwt.core.client.CodeDownloadException;
|
||||
import com.google.gwt.core.client.EntryPoint;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.core.client.ScriptInjector;
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.dom.client.Document;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
@@ -84,12 +81,9 @@ import com.google.gwt.user.client.ui.RootPanel;
|
||||
import com.google.gwtexpui.clippy.client.CopyableLabel;
|
||||
import com.google.gwtexpui.user.client.UserAgent;
|
||||
import com.google.gwtexpui.user.client.ViewSite;
|
||||
import com.google.gwtjsonrpc.client.CallbackHandle;
|
||||
import com.google.gwtjsonrpc.client.JsonDefTarget;
|
||||
import com.google.gwtjsonrpc.client.JsonUtil;
|
||||
import com.google.gwtjsonrpc.client.XsrfManager;
|
||||
import com.google.gwtjsonrpc.client.impl.ResultDeserializer;
|
||||
import com.google.gwtjsonrpc.common.AsyncCallback;
|
||||
import com.google.gwtorm.client.KeyUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -571,7 +565,7 @@ public class Gerrit implements EntryPoint {
|
||||
}
|
||||
|
||||
saveDefaultTheme();
|
||||
loadPlugins(hpd, token);
|
||||
PluginLoader.load(hpd.plugins, token);
|
||||
}
|
||||
|
||||
private void saveDefaultTheme() {
|
||||
@@ -580,53 +574,6 @@ public class Gerrit implements EntryPoint {
|
||||
Document.get().getElementById("gerrit_footer"));
|
||||
}
|
||||
|
||||
private void loadPlugins(HostPageData hpd, final String token) {
|
||||
if (hpd.plugins != null && !hpd.plugins.isEmpty()) {
|
||||
for (final String url : hpd.plugins) {
|
||||
ScriptInjector.fromUrl(url)
|
||||
.setWindow(ScriptInjector.TOP_WINDOW)
|
||||
.setCallback(new Callback<Void, Exception>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception reason) {
|
||||
ErrorDialog d;
|
||||
if (reason instanceof CodeDownloadException) {
|
||||
d = new ErrorDialog(M.cannotDownloadPlugin(url));
|
||||
} else {
|
||||
d = new ErrorDialog(M.pluginFailed(url));
|
||||
}
|
||||
d.center();
|
||||
}
|
||||
}).inject();
|
||||
}
|
||||
}
|
||||
|
||||
CallbackHandle<Void> cb = new CallbackHandle<Void>(
|
||||
new ResultDeserializer<Void>() {
|
||||
@Override
|
||||
public Void fromResult(JavaScriptObject responseObject) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
display(token);
|
||||
}
|
||||
});
|
||||
cb.install();
|
||||
ScriptInjector.fromString(cb.getFunctionName() + "();")
|
||||
.setWindow(ScriptInjector.TOP_WINDOW)
|
||||
.inject();
|
||||
}
|
||||
|
||||
public static void refreshMenuBar() {
|
||||
menuLeft.clear();
|
||||
menuRight.clear();
|
||||
|
||||
Reference in New Issue
Block a user