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:
Shawn Pearce
2013-12-09 08:20:44 -08:00
parent d7f80ca621
commit c8e96ad49d
16 changed files with 428 additions and 164 deletions

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012 The Android Open Source Project
// 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.
@@ -14,21 +14,46 @@
package com.google.gerrit.plugin.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
/**
* Base class for writing Gerrit Web UI plugins
* Wrapper around the plugin instance exposed by Gerrit.
*
* Writing a plugin:
* <ol>
* <li>Declare subtype of Plugin</li>
* <li>Bind WebUiPlugin to GwtPlugin implementation in Gerrit-Module</li>
* </ol>
* Listeners for events generated by the main UI must be registered
* through this instance.
*/
public abstract class Plugin implements EntryPoint {
public native static void go(String t)
/*-{ $wnd.Gerrit.go(t) }-*/;
public final class Plugin extends JavaScriptObject {
private static final Plugin self = install(
GWT.getModuleBaseURL() + GWT.getModuleName() + ".nocache.js");
public native static void refresh()
/*-{ $wnd.Gerrit.refresh() }-*/;
/** Obtain the plugin instance wrapper. */
public static Plugin get() {
return self;
}
/** Installed name of the plugin. */
public final String getName() {
return getPluginName();
}
/** Installed name of the plugin. */
public final native String getPluginName()
/*-{ return this.getPluginName() }-*/;
/** Navigate the UI to the screen identified by the token. */
public final native void go(String token)
/*-{ return this.go(token) }-*/;
/** Refresh the current UI. */
public final native void refresh()
/*-{ return this.refresh() }-*/;
protected Plugin() {
}
native void _initialized() /*-{ this._success = true }-*/;
native void _loaded() /*-{ this._loadedGwt() }-*/;
private static native final Plugin install(String u)
/*-{ return $wnd.Gerrit.installGwt(u) }-*/;
}

View File

@@ -0,0 +1,44 @@
// Copyright (C) 2012 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.plugin.client;
import com.google.gwt.core.client.EntryPoint;
/**
* Base class for writing Gerrit Web UI plugins
*
* Writing a plugin:
* <ol>
* <li>Declare subtype of Plugin</li>
* <li>Bind WebUiPlugin to GwtPlugin implementation in Gerrit-Module</li>
* </ol>
*/
public abstract class PluginEntryPoint implements EntryPoint {
/**
* The plugin entry point method, called automatically by loading
* a module that declares an implementing class as an entry point.
*/
public abstract void onPluginLoad();
public final void onModuleLoad() {
Plugin self = Plugin.get();
try {
onPluginLoad();
self._initialized();
} finally {
self._loaded();
}
}
}