Add support for disconnection glass panel in Safari plugin.
Patch by: bobv
Review by: scottb
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7135 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/webkit/Core/WebScriptSessionHandler.cpp b/plugins/webkit/Core/WebScriptSessionHandler.cpp
index 2cc288b..7a4d8fa 100644
--- a/plugins/webkit/Core/WebScriptSessionHandler.cpp
+++ b/plugins/webkit/Core/WebScriptSessionHandler.cpp
@@ -91,6 +91,10 @@
pthread_mutex_destroy(&javaObjectsLock);
}
+void WebScriptSessionHandler::disconnectDetectedImpl() {
+ crashHandler->crash(__PRETTY_FUNCTION__, "Server disconnect detected");
+}
+
void WebScriptSessionHandler::fatalError(HostChannel& channel,
const std::string& message) {
// TODO: better way of reporting error?
@@ -269,48 +273,53 @@
*/
Debug::log(Debug::Debugging) << "Java method " << dispatchId << " invoked" << Debug::flush;
- /*
- * If a JS function is evaluated without an meaningful this object or the global
- * object is implicitly used as the this object, we'll assume that the
- * Java-derived method is static, and send a null this object to the server
- */
- Value thisValue;
- if (JSValueIsEqual(contextRef, thisObject, JSContextGetGlobalObject(contextRef), NULL)) {
- thisValue = Value();
- thisValue.setNull();
- } else {
- makeValue(thisValue, thisObject);
- }
-
- // Argument conversion is straightforward
- Value args[argumentCount];
- for (int i = 0; i < argumentCount; i++) {
- makeValue(args[i], arguments[i]);
- }
-
- if (!InvokeMessage::send(*channel, thisValue, dispatchId,
- argumentCount, args)) {
- initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to send invocation message");
- *exception = makeException("Unable to send invocation message");
- return JSValueMakeUndefined(contextRef);
- }
-
- scoped_ptr<ReturnMessage> ret(channel->reactToMessagesWhileWaitingForReturn(sessionHandler));
-
- if (!ret.get()) {
- initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to receive return message");
- *exception = makeException("Unable to receive return message");
- return JSValueMakeUndefined(contextRef);
- }
-
- Value v = ret->getReturnValue();
-
JSValueRef toReturn;
- if (ret->isException()) {
- *exception = makeValueRef(v);
- toReturn = JSValueMakeUndefined(contextRef);
+ if (crashHandler->hasCrashed()) {
+ Debug::log(Debug::Debugging) << "Not executing method since we have crashed" << Debug::flush;
+ toReturn = JSValueMakeUndefined(contextRef);
} else {
- toReturn = makeValueRef(v);
+ /*
+ * If a JS function is evaluated without an meaningful this object or the global
+ * object is implicitly used as the this object, we'll assume that the
+ * Java-derived method is static, and send a null this object to the server
+ */
+ Value thisValue;
+ if (JSValueIsEqual(contextRef, thisObject, JSContextGetGlobalObject(contextRef), NULL)) {
+ thisValue = Value();
+ thisValue.setNull();
+ } else {
+ makeValue(thisValue, thisObject);
+ }
+
+ // Argument conversion is straightforward
+ Value args[argumentCount];
+ for (int i = 0; i < argumentCount; i++) {
+ makeValue(args[i], arguments[i]);
+ }
+
+ if (!InvokeMessage::send(*channel, thisValue, dispatchId,
+ argumentCount, args)) {
+ initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to send invocation message");
+ *exception = makeException("Unable to send invocation message");
+ return JSValueMakeUndefined(contextRef);
+ }
+
+ scoped_ptr<ReturnMessage> ret(channel->reactToMessagesWhileWaitingForReturn(sessionHandler));
+
+ if (!ret.get()) {
+ initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to receive return message");
+ *exception = makeException("Unable to receive return message");
+ return JSValueMakeUndefined(contextRef);
+ }
+
+ Value v = ret->getReturnValue();
+
+ if (ret->isException()) {
+ *exception = makeValueRef(v);
+ toReturn = JSValueMakeUndefined(contextRef);
+ } else {
+ toReturn = makeValueRef(v);
+ }
}
JSValueRef makeResultArguments[] = {JSValueMakeBoolean(contextRef, false), toReturn};
@@ -334,6 +343,11 @@
JSValueRef WebScriptSessionHandler::javaObjectGetPropertyImpl (TrackingDataRef tracker, JSObjectRef object,
JSStringRef propertyName, JSValueRef* exception) {
*exception = NULL;
+
+ if (crashHandler->hasCrashed()) {
+ Debug::log(Debug::Debugging) << "Not executing since we have crashed" << Debug::flush;
+ return JSValueMakeUndefined(contextRef);
+ }
// Convert the name
int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
@@ -403,6 +417,12 @@
bool WebScriptSessionHandler::javaObjectSetPropertyImpl (TrackingDataRef tracker, JSObjectRef object,
JSStringRef propertyName, JSValueRef jsValue,
JSValueRef* exception) {
+
+ if (crashHandler->hasCrashed()) {
+ Debug::log(Debug::Debugging) << "Not executing since we have crashed" << Debug::flush;
+ return true;
+ }
+
int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
scoped_array<char> propertyNameChars(new char[maxLength]);
JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
diff --git a/plugins/webkit/Core/WebScriptSessionHandler.h b/plugins/webkit/Core/WebScriptSessionHandler.h
index 486f523..5e05385 100644
--- a/plugins/webkit/Core/WebScriptSessionHandler.h
+++ b/plugins/webkit/Core/WebScriptSessionHandler.h
@@ -25,6 +25,7 @@
class CrashHandler {
public:
virtual void crash(const char* functionName, const char* message) = 0;
+ virtual bool hasCrashed() = 0;
};
typedef CrashHandler* CrashHandlerRef;
@@ -88,6 +89,7 @@
JSValueRef makeException(const char* message);
protected:
+ virtual void disconnectDetectedImpl();
virtual void fatalError(HostChannel& channel, const std::string& message);
virtual void freeValue(HostChannel& channel, int idCount, const int* ids);
virtual void loadJsni(HostChannel& channel, const std::string& js);
diff --git a/plugins/webkit/Plugin/OophmWebScriptObject.mm b/plugins/webkit/Plugin/OophmWebScriptObject.mm
index ad06685..f40522a 100644
--- a/plugins/webkit/Plugin/OophmWebScriptObject.mm
+++ b/plugins/webkit/Plugin/OophmWebScriptObject.mm
@@ -19,7 +19,6 @@
#import <WebKit/WebKit.h>
#import "BrowserChannel.h"
#import "Debug.h"
-#import "GTMStackTrace.h"
#import "GTMSystemVersion.h"
#import "NSMutableString+HtmlReplacement.h"
#import "LoadModuleMessage.h"
@@ -41,6 +40,7 @@
NSString* str = [NSString stringWithFormat:@"%s\n\n%s", message, functionName];
[obj crashWithMessage:str];
}
+ virtual bool hasCrashed();
private:
OophmWebScriptObject* const obj;
};
@@ -48,6 +48,7 @@
@interface OophmWebScriptObject (Private)
+ (void)logAndThrowString: (NSString*)message;
- (void)addAllowedHost: (NSString*)host;
+- (BOOL)hasCrashed;
- (void)connectAlertDidEnd: (NSAlert*)alert
returnCode: (int)returnCode
contextInfo: (void*)contextInfo;
@@ -59,6 +60,11 @@
@end
+// This is declared here so that we can access the category method
+bool PluginCrashHandler::hasCrashed() {
+ return [obj hasCrashed] ? true : false;
+}
+
@implementation OophmWebScriptObject
+ (void)initialize {
// Add the plugin's bundle name to the user defaults search path
@@ -188,7 +194,27 @@
return;
}
self->_hasCrashed = YES;
+
+#ifdef GWT_DEBUGDISABLE
+ // We'll call out to the JS support function
+ JSGlobalContextRef contextRef = self->_contextRef;
+ JSStringRef disconnectedName = JSStringCreateWithUTF8CString("__gwt_disconnected");
+ JSValueRef disconnected = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef), disconnectedName, NULL);
+ JSStringRelease(disconnectedName);
+
+ if (JSValueIsObject(contextRef, disconnected)) {
+ // Found hosted.html's crash support
+ JSObjectRef disconnectedFunction = JSValueToObject(contextRef, disconnected, NULL);
+ JSValueRef exception = NULL;
+ JSObjectCallAsFunction(contextRef, disconnectedFunction, JSContextGetGlobalObject(contextRef), 0, NULL, &exception);
+ if (!exception) {
+ // Couldn't invoke the crash handler.
+ return;
+ }
+ }
+#endif //GWT_DEBUGDISABLE
+ // Use a simple crash page built into the bundle
NSBundle* oophmBundle = [NSBundle bundleForClass:[self class]];
NSString* path = [oophmBundle pathForResource:@"crash" ofType:@"html"];
NSMutableString* crashPage = [NSMutableString stringWithContentsOfFile:path];
@@ -266,6 +292,10 @@
[shared synchronize];
}
+- (BOOL)hasCrashed{
+ return self->_hasCrashed;
+}
+
- (void)connectAlertDidEnd:(NSAlert *)alert
returnCode:(int)returnCode
contextInfo:(void *)contextInfo {