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();
|
||||
|
@@ -20,6 +20,7 @@ public interface GerritConstants extends Constants {
|
||||
String menuSignIn();
|
||||
String menuRegister();
|
||||
String reportBug();
|
||||
String loadingPlugins();
|
||||
|
||||
String signInDialogTitle();
|
||||
String signInDialogClose();
|
||||
|
@@ -1,6 +1,7 @@
|
||||
menuSignIn = Sign In
|
||||
menuRegister = Register
|
||||
reportBug = Report Bug
|
||||
loadingPlugins = Loading plugins ...
|
||||
|
||||
signInDialogTitle = Code Review - Sign In
|
||||
signInDialogClose = Close
|
||||
|
@@ -116,6 +116,7 @@ public interface GerritCss extends CssResource {
|
||||
String errorDialogGlass();
|
||||
String errorDialogText();
|
||||
String errorDialogTitle();
|
||||
String loadingPluginsDialog();
|
||||
String fileColumnHeader();
|
||||
String fileCommentBorder();
|
||||
String fileLine();
|
||||
|
@@ -13,7 +13,7 @@ branchCreationNotAllowedUnderRefnamePrefix = Branch creation is not allowed unde
|
||||
branchAlreadyExists = A branch with the name {0} already exists.
|
||||
branchCreationConflict = Cannot create branch {0} since it conflicts with branch {1}.
|
||||
|
||||
pluginFailed = Plugin JavaScript {0} failed to load
|
||||
cannotDownloadPlugin = Cannot download JavaScript plugin from: {0}.
|
||||
pluginFailed = Plugin "{0}" failed to load
|
||||
cannotDownloadPlugin = Cannot load plugin from {0}
|
||||
|
||||
parentUpdateFailed = Setting parent project failed: {0}
|
||||
|
@@ -15,6 +15,8 @@
|
||||
package com.google.gerrit.client.api;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.rpc.NativeString;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.core.client.JsArray;
|
||||
import com.google.gwt.user.client.History;
|
||||
@@ -24,29 +26,36 @@ public class ApiGlue {
|
||||
private static String pluginName;
|
||||
|
||||
public static void init() {
|
||||
init0();
|
||||
init0(GWT.getHostPageBaseURL(), NativeString.TYPE);
|
||||
ActionContext.init();
|
||||
Plugin.init();
|
||||
addHistoryHook();
|
||||
}
|
||||
|
||||
private static native void init0() /*-{
|
||||
var serverUrl = @com.google.gwt.core.client.GWT::getHostPageBaseURL()();
|
||||
var Plugin = function (name){this.name = name};
|
||||
var Gerrit = {
|
||||
private static native void init0(String serverUrl, JavaScriptObject JsonString) /*-{
|
||||
$wnd.Gerrit = {
|
||||
JsonString: JsonString,
|
||||
events: {},
|
||||
plugins: {},
|
||||
change_actions: {},
|
||||
revision_actions: {},
|
||||
project_actions: {},
|
||||
|
||||
getPluginName: @com.google.gerrit.client.api.ApiGlue::getPluginName(),
|
||||
install: function (f) {
|
||||
var p = new Plugin(this.getPluginName());
|
||||
@com.google.gerrit.client.api.ApiGlue::install(Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gerrit/client/api/JsUiPlugin;)(f,p);
|
||||
var p = this._getPluginByUrl(@com.google.gerrit.client.api.PluginName::getCallerUrl()());
|
||||
@com.google.gerrit.client.api.ApiGlue::install(Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gerrit/client/api/Plugin;)(f,p);
|
||||
},
|
||||
installGwt: function(u){return this._getPluginByUrl(u)},
|
||||
_getPluginByUrl: function(u) {
|
||||
return u.indexOf(serverUrl) == 0
|
||||
? this.plugins[u.substring(serverUrl.length)]
|
||||
: this.plugins[u]
|
||||
},
|
||||
|
||||
go: @com.google.gerrit.client.api.ApiGlue::go(Ljava/lang/String;),
|
||||
refresh: @com.google.gerrit.client.api.ApiGlue::refresh(),
|
||||
|
||||
events: {},
|
||||
change_actions: {},
|
||||
revision_actions: {},
|
||||
project_actions: {},
|
||||
|
||||
on: function (e,f){(this.events[e] || (this.events[e]=[])).push(f)},
|
||||
onAction: function (t,n,c){this._onAction(this.getPluginName(),t,n,c)},
|
||||
_onAction: function (p,t,n,c) {
|
||||
@@ -81,34 +90,7 @@ public class ApiGlue {
|
||||
}
|
||||
},
|
||||
'delete': function(u,b){@com.google.gerrit.client.api.ActionContext::delete(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),b)},
|
||||
JsonString: @com.google.gerrit.client.rpc.NativeString::TYPE,
|
||||
};
|
||||
|
||||
Plugin.prototype = {
|
||||
getPluginName: function(){return this.name},
|
||||
go: @com.google.gerrit.client.api.ApiGlue::go(Ljava/lang/String;),
|
||||
refresh: Gerrit.refresh,
|
||||
onAction: function(t,n,c) {Gerrit._onAction(this.name,t,n,c)},
|
||||
|
||||
url: function (d) {
|
||||
var u = serverUrl + 'plugins/' + this.name + '/';
|
||||
if (d && d.length > 0) u += d.charAt(0)=='/' ? d.substring(1) : d;
|
||||
return u;
|
||||
},
|
||||
|
||||
_api: function(d) {
|
||||
var u = 'plugins/' + this.name + '/';
|
||||
if (d && d.length > 0) u += d.charAt(0)=='/' ? d.substring(1) : d;
|
||||
return @com.google.gerrit.client.rpc.RestApi::new(Ljava/lang/String;)(u);
|
||||
},
|
||||
|
||||
get: function(u,b){@com.google.gerrit.client.api.ActionContext::get(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),b)},
|
||||
post: function(u,i,b){@com.google.gerrit.client.api.ActionContext::post(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),i,b)},
|
||||
put: function(u,i,b){@com.google.gerrit.client.api.ActionContext::put(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),i,b)},
|
||||
'delete': function(u,b){@com.google.gerrit.client.api.ActionContext::delete(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),b)},
|
||||
};
|
||||
|
||||
$wnd.Gerrit = Gerrit;
|
||||
}-*/;
|
||||
|
||||
/** Install deprecated {@code gerrit_addHistoryHook()} function. */
|
||||
@@ -119,17 +101,25 @@ public class ApiGlue {
|
||||
};
|
||||
}-*/;
|
||||
|
||||
private static void install(JavaScriptObject cb, JsUiPlugin p) {
|
||||
private static void install(JavaScriptObject cb, Plugin p) throws Exception {
|
||||
try {
|
||||
pluginName = p.name();
|
||||
invoke(cb, p);
|
||||
p._initialized();
|
||||
} catch (Exception e) {
|
||||
p.failure(e);
|
||||
throw e;
|
||||
} finally {
|
||||
pluginName = null;
|
||||
PluginLoader.loaded();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String getPluginName() {
|
||||
return pluginName != null ? pluginName : PluginName.get();
|
||||
if (pluginName != null) {
|
||||
return pluginName;
|
||||
}
|
||||
return PluginName.fromUrl(PluginName.getCallerUrl());
|
||||
}
|
||||
|
||||
private static final void go(String urlOrToken) {
|
||||
|
@@ -1,24 +0,0 @@
|
||||
// Copyright (C) 2013 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.
|
||||
|
||||
package com.google.gerrit.client.api;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
|
||||
class JsUiPlugin extends JavaScriptObject {
|
||||
final native String name() /*-{ return this.name }-*/;
|
||||
|
||||
protected JsUiPlugin() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
// Copyright (C) 2013 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.
|
||||
|
||||
package com.google.gerrit.client.api;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
|
||||
final class Plugin extends JavaScriptObject {
|
||||
private static final JavaScriptObject TYPE = createType();
|
||||
|
||||
static Plugin create(String url) {
|
||||
int s = "plugins/".length();
|
||||
int e = url.indexOf('/', s);
|
||||
String name = url.substring(s, e);
|
||||
return create(TYPE, url, name);
|
||||
}
|
||||
|
||||
final native String url() /*-{ return this._scriptUrl }-*/;
|
||||
final native String name() /*-{ return this.name }-*/;
|
||||
|
||||
final native boolean loaded() /*-{ return this._success || this._failure != null }-*/;
|
||||
final native Exception failure() /*-{ return this._failure }-*/;
|
||||
final native void failure(Exception e) /*-{ this._failure = e }-*/;
|
||||
final native boolean success() /*-{ return this._success || false }-*/;
|
||||
final native void _initialized() /*-{ this._success = true }-*/;
|
||||
|
||||
private static native Plugin create(JavaScriptObject T, String u, String n)
|
||||
/*-{ return new T(u,n) }-*/;
|
||||
|
||||
private static native JavaScriptObject createType() /*-{
|
||||
function Plugin(u, n) {
|
||||
this._scriptUrl = u;
|
||||
this.name = n;
|
||||
}
|
||||
return Plugin;
|
||||
}-*/;
|
||||
|
||||
static native void init() /*-{
|
||||
var G = $wnd.Gerrit;
|
||||
@com.google.gerrit.client.api.Plugin::TYPE.prototype = {
|
||||
getPluginName: function(){return this.name},
|
||||
go: @com.google.gerrit.client.api.ApiGlue::go(Ljava/lang/String;),
|
||||
refresh: @com.google.gerrit.client.api.ApiGlue::refresh(),
|
||||
on: G.on,
|
||||
onAction: function(t,n,c){G._onAction(this.name,t,n,c)},
|
||||
|
||||
url: function (u){return G.url(this._url(u))},
|
||||
get: function(u,b){@com.google.gerrit.client.api.ActionContext::get(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),b)},
|
||||
post: function(u,i,b){@com.google.gerrit.client.api.ActionContext::post(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),i,b)},
|
||||
put: function(u,i,b){@com.google.gerrit.client.api.ActionContext::put(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),i,b)},
|
||||
'delete': function(u,b){@com.google.gerrit.client.api.ActionContext::delete(Lcom/google/gerrit/client/rpc/RestApi;Lcom/google/gwt/core/client/JavaScriptObject;)(this._api(u),b)},
|
||||
|
||||
_loadedGwt: function(){@com.google.gerrit.client.api.PluginLoader::loaded()()},
|
||||
_api: function(u){return @com.google.gerrit.client.rpc.RestApi::new(Ljava/lang/String;)(this._url(u))},
|
||||
_url: function (d) {
|
||||
var u = 'plugins/' + this.name + '/';
|
||||
if (d && d.length > 0)
|
||||
return u + (d.charAt(0)=='/' ? d.substring(1) : d);
|
||||
return u;
|
||||
},
|
||||
};
|
||||
}-*/;
|
||||
|
||||
protected Plugin() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,185 @@
|
||||
// Copyright (C) 2013 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.
|
||||
|
||||
package com.google.gerrit.client.api;
|
||||
|
||||
import com.google.gerrit.client.ErrorDialog;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.rpc.NativeMap;
|
||||
import com.google.gerrit.client.rpc.Natives;
|
||||
import com.google.gwt.core.client.Callback;
|
||||
import com.google.gwt.core.client.CodeDownloadException;
|
||||
import com.google.gwt.core.client.ScriptInjector;
|
||||
import com.google.gwt.user.client.Timer;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.DialogBox;
|
||||
import com.google.gwtexpui.progress.client.ProgressBar;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Loads JavaScript plugins with a progress meter visible. */
|
||||
public class PluginLoader extends DialogBox {
|
||||
private static final int MAX_LOAD_TIME_MILLIS = 5000;
|
||||
private static PluginLoader self;
|
||||
|
||||
public static void load(List<String> plugins, final String token) {
|
||||
if (plugins == null || plugins.isEmpty()) {
|
||||
Gerrit.display(token);
|
||||
} else {
|
||||
self = new PluginLoader(token);
|
||||
self.load(plugins);
|
||||
self.startTimers();
|
||||
self.center();
|
||||
}
|
||||
}
|
||||
|
||||
static void loaded() {
|
||||
self.loadedOne();
|
||||
}
|
||||
|
||||
private final String token;
|
||||
private ProgressBar progress;
|
||||
private Timer show;
|
||||
private Timer update;
|
||||
private Timer timeout;
|
||||
private boolean visible;
|
||||
|
||||
private PluginLoader(String tokenToDisplay) {
|
||||
super(/* auto hide */false, /* modal */true);
|
||||
token = tokenToDisplay;
|
||||
progress = new ProgressBar(Gerrit.C.loadingPlugins());
|
||||
|
||||
setStyleName(Gerrit.RESOURCES.css().errorDialog());
|
||||
addStyleName(Gerrit.RESOURCES.css().loadingPluginsDialog());
|
||||
}
|
||||
|
||||
private void load(List<String> pluginUrls) {
|
||||
for (String url : pluginUrls) {
|
||||
Plugin plugin = Plugin.create(url);
|
||||
plugins().put(url, plugin);
|
||||
ScriptInjector.fromUrl(url)
|
||||
.setWindow(ScriptInjector.TOP_WINDOW)
|
||||
.setCallback(new LoadCallback(plugin))
|
||||
.inject();
|
||||
}
|
||||
}
|
||||
|
||||
private void startTimers() {
|
||||
show = new Timer() {
|
||||
@Override
|
||||
public void run() {
|
||||
setText(Window.getTitle());
|
||||
setWidget(progress);
|
||||
setGlassEnabled(true);
|
||||
getGlassElement().addClassName(Gerrit.RESOURCES.css().errorDialogGlass());
|
||||
hide(true);
|
||||
center();
|
||||
visible = true;
|
||||
}
|
||||
};
|
||||
show.schedule(500);
|
||||
|
||||
update = new Timer() {
|
||||
private int cycle;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
progress.setValue(100 * ++cycle * 250 / MAX_LOAD_TIME_MILLIS);
|
||||
}
|
||||
};
|
||||
update.scheduleRepeating(250);
|
||||
|
||||
timeout = new Timer() {
|
||||
@Override
|
||||
public void run() {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
timeout.schedule(MAX_LOAD_TIME_MILLIS);
|
||||
}
|
||||
|
||||
private void loadedOne() {
|
||||
boolean done = true;
|
||||
for (Plugin plugin : Natives.asList(plugins().values())) {
|
||||
done &= plugin.loaded();
|
||||
}
|
||||
if (done) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void finish() {
|
||||
show.cancel();
|
||||
update.cancel();
|
||||
timeout.cancel();
|
||||
self = null;
|
||||
|
||||
if (!hadFailures()) {
|
||||
if (visible) {
|
||||
progress.setValue(100);
|
||||
new Timer() {
|
||||
@Override
|
||||
public void run() {
|
||||
hide(true);
|
||||
}
|
||||
}.schedule(250);
|
||||
} else {
|
||||
hide(true);
|
||||
}
|
||||
}
|
||||
|
||||
Gerrit.display(token);
|
||||
}
|
||||
|
||||
private boolean hadFailures() {
|
||||
boolean failed = false;
|
||||
for (Plugin plugin : Natives.asList(plugins().values())) {
|
||||
if (!plugin.success()) {
|
||||
failed = true;
|
||||
|
||||
Exception e = plugin.failure();
|
||||
String msg;
|
||||
if (e != null && e instanceof CodeDownloadException) {
|
||||
msg = Gerrit.M.cannotDownloadPlugin(plugin.url());
|
||||
} else {
|
||||
msg = Gerrit.M.pluginFailed(plugin.name());
|
||||
}
|
||||
hide(true);
|
||||
new ErrorDialog(msg).center();
|
||||
}
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
private static native NativeMap<Plugin> plugins()
|
||||
/*-{ return $wnd.Gerrit.plugins }-*/;
|
||||
|
||||
private class LoadCallback implements Callback<Void, Exception> {
|
||||
private final Plugin plugin;
|
||||
|
||||
LoadCallback(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception reason) {
|
||||
plugin.failure(reason);
|
||||
loadedOne();
|
||||
}
|
||||
}
|
||||
}
|
@@ -31,14 +31,29 @@ import com.google.gwt.core.client.impl.StackTraceCreator;
|
||||
class PluginName {
|
||||
private static final String UNKNOWN = "<unknown>";
|
||||
|
||||
static String get() {
|
||||
return GWT.<PluginName> create(PluginName.class).guessName();
|
||||
private static String baseUrl() {
|
||||
return GWT.getHostPageBaseURL() + "plugins/";
|
||||
}
|
||||
|
||||
String guessName() {
|
||||
static String getCallerUrl() {
|
||||
return GWT.<PluginName> create(PluginName.class).findCallerUrl();
|
||||
}
|
||||
|
||||
static String fromUrl(String url) {
|
||||
String baseUrl = baseUrl();
|
||||
if (url != null && url.startsWith(baseUrl)) {
|
||||
int s = url.indexOf('/', baseUrl.length());
|
||||
if (s > 0) {
|
||||
return url.substring(baseUrl.length(), s);
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
String findCallerUrl() {
|
||||
JavaScriptException err = makeException();
|
||||
if (hasStack(err)) {
|
||||
return PluginNameMoz.guessName(err);
|
||||
return PluginNameMoz.getUrl(err);
|
||||
}
|
||||
|
||||
String baseUrl = baseUrl();
|
||||
@@ -46,19 +61,12 @@ class PluginName {
|
||||
for (int i = trace.length - 1; i >= 0; i--) {
|
||||
String u = trace[i].getFileName();
|
||||
if (u != null && u.startsWith(baseUrl)) {
|
||||
int s = u.indexOf('/', baseUrl.length());
|
||||
if (s > 0) {
|
||||
return u.substring(baseUrl.length(), s);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
private static String baseUrl() {
|
||||
return GWT.getHostPageBaseURL() + "plugins/";
|
||||
}
|
||||
|
||||
private static StackTraceElement[] getTrace(JavaScriptException err) {
|
||||
StackTraceCreator.fillInStackTrace(err);
|
||||
return err.getStackTrace();
|
||||
@@ -72,21 +80,22 @@ class PluginName {
|
||||
|
||||
/** Extracts URL from the stack frame. */
|
||||
static class PluginNameMoz extends PluginName {
|
||||
String guessName() {
|
||||
return guessName(makeException());
|
||||
String findCallerUrl() {
|
||||
return getUrl(makeException());
|
||||
}
|
||||
|
||||
static String guessName(JavaScriptException e) {
|
||||
private static String getUrl(JavaScriptException e) {
|
||||
String baseUrl = baseUrl();
|
||||
JsArrayString stack = getStack(e);
|
||||
for (int i = stack.length() - 1; i >= 0; i--) {
|
||||
String frame = stack.get(i);
|
||||
int at = frame.indexOf(baseUrl);
|
||||
if (at >= 0) {
|
||||
int s = frame.indexOf('/', at + baseUrl.length());
|
||||
if (s > 0) {
|
||||
return frame.substring(at + baseUrl.length(), s);
|
||||
int end = frame.indexOf(':', at + baseUrl.length());
|
||||
if (end < 0) {
|
||||
end = frame.length();
|
||||
}
|
||||
return frame.substring(at, end);
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
|
@@ -431,6 +431,11 @@ a:hover {
|
||||
font-size: 15px;
|
||||
font-family: verdana;
|
||||
}
|
||||
.loadingPluginsDialog {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
|
||||
/** Screen **/
|
||||
|
Reference in New Issue
Block a user