You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.6 KiB
170 lines
4.6 KiB
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
(function() {
|
|
var internal = mojo.internal;
|
|
|
|
function Connector(handle) {
|
|
if (!(handle instanceof MojoHandle))
|
|
throw new Error("Connector: not a handle " + handle);
|
|
this.handle_ = handle;
|
|
this.dropWrites_ = false;
|
|
this.error_ = false;
|
|
this.incomingReceiver_ = null;
|
|
this.readWatcher_ = null;
|
|
this.errorHandler_ = null;
|
|
this.paused_ = false;
|
|
|
|
this.waitToReadMore();
|
|
}
|
|
|
|
Connector.prototype.close = function() {
|
|
this.cancelWait();
|
|
if (this.handle_ != null) {
|
|
this.handle_.close();
|
|
this.handle_ = null;
|
|
}
|
|
};
|
|
|
|
Connector.prototype.pauseIncomingMethodCallProcessing = function() {
|
|
if (this.paused_) {
|
|
return;
|
|
}
|
|
this.paused_= true;
|
|
this.cancelWait();
|
|
};
|
|
|
|
Connector.prototype.resumeIncomingMethodCallProcessing = function() {
|
|
if (!this.paused_) {
|
|
return;
|
|
}
|
|
this.paused_= false;
|
|
this.waitToReadMore();
|
|
};
|
|
|
|
Connector.prototype.accept = function(message) {
|
|
if (this.error_)
|
|
return false;
|
|
|
|
if (this.dropWrites_)
|
|
return true;
|
|
|
|
var result = this.handle_.writeMessage(
|
|
new Uint8Array(message.buffer.arrayBuffer), message.handles);
|
|
switch (result) {
|
|
case Mojo.RESULT_OK:
|
|
// The handles were successfully transferred, so we don't own them
|
|
// anymore.
|
|
message.handles = [];
|
|
break;
|
|
case Mojo.RESULT_FAILED_PRECONDITION:
|
|
// There's no point in continuing to write to this pipe since the other
|
|
// end is gone. Avoid writing any future messages. Hide write failures
|
|
// from the caller since we'd like them to continue consuming any
|
|
// backlog of incoming messages before regarding the message pipe as
|
|
// closed.
|
|
this.dropWrites_ = true;
|
|
break;
|
|
default:
|
|
// This particular write was rejected, presumably because of bad input.
|
|
// The pipe is not necessarily in a bad state.
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
Connector.prototype.setIncomingReceiver = function(receiver) {
|
|
this.incomingReceiver_ = receiver;
|
|
};
|
|
|
|
Connector.prototype.setErrorHandler = function(handler) {
|
|
this.errorHandler_ = handler;
|
|
};
|
|
|
|
Connector.prototype.readMore_ = function(result) {
|
|
for (;;) {
|
|
if (this.paused_) {
|
|
return;
|
|
}
|
|
|
|
var read = this.handle_.readMessage();
|
|
if (this.handle_ == null) // The connector has been closed.
|
|
return;
|
|
if (read.result == Mojo.RESULT_SHOULD_WAIT)
|
|
return;
|
|
if (read.result != Mojo.RESULT_OK) {
|
|
this.handleError(read.result !== Mojo.RESULT_FAILED_PRECONDITION,
|
|
false);
|
|
return;
|
|
}
|
|
var messageBuffer = new internal.Buffer(read.buffer);
|
|
var message = new internal.Message(messageBuffer, read.handles);
|
|
var receiverResult = this.incomingReceiver_ &&
|
|
this.incomingReceiver_.accept(message);
|
|
|
|
// Dispatching the message may have closed the connector.
|
|
if (this.handle_ == null)
|
|
return;
|
|
|
|
// Handle invalid incoming message.
|
|
if (!internal.isTestingMode() && !receiverResult) {
|
|
// TODO(yzshen): Consider notifying the embedder.
|
|
this.handleError(true, false);
|
|
}
|
|
}
|
|
};
|
|
|
|
Connector.prototype.cancelWait = function() {
|
|
if (this.readWatcher_) {
|
|
this.readWatcher_.cancel();
|
|
this.readWatcher_ = null;
|
|
}
|
|
};
|
|
|
|
Connector.prototype.waitToReadMore = function() {
|
|
if (this.handle_) {
|
|
this.readWatcher_ = this.handle_.watch({readable: true},
|
|
this.readMore_.bind(this));
|
|
}
|
|
};
|
|
|
|
Connector.prototype.handleError = function(forcePipeReset,
|
|
forceAsyncHandler) {
|
|
if (this.error_ || this.handle_ === null) {
|
|
return;
|
|
}
|
|
|
|
if (this.paused_) {
|
|
// Enforce calling the error handler asynchronously if the user has
|
|
// paused receiving messages. We need to wait until the user starts
|
|
// receiving messages again.
|
|
forceAsyncHandler = true;
|
|
}
|
|
|
|
if (!forcePipeReset && forceAsyncHandler) {
|
|
forcePipeReset = true;
|
|
}
|
|
|
|
this.cancelWait();
|
|
if (forcePipeReset) {
|
|
this.handle_.close();
|
|
var dummyPipe = Mojo.createMessagePipe();
|
|
this.handle_ = dummyPipe.handle0;
|
|
}
|
|
|
|
if (forceAsyncHandler) {
|
|
if (!this.paused_) {
|
|
this.waitToReadMore();
|
|
}
|
|
} else {
|
|
this.error_ = true;
|
|
if (this.errorHandler_) {
|
|
this.errorHandler_.onError();
|
|
}
|
|
}
|
|
};
|
|
|
|
internal.Connector = Connector;
|
|
})();
|