Don't serialize config dictionary in Native Messaging interface.

The config dictionary is no longer serialized when passing
it between the web-app and the native messaging host. It is
still serialized for the NPAPI plugin, however, since it's
difficult to return JavaScript objects from a NPAPI plugin.

BUG=232135

Review URL: https://chromiumcodereview.appspot.com/15623002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202029 0039d316-1c4b-4281-b951-d872f2087c98
parent ba92ce0b
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/location.h" #include "base/location.h"
#include "base/strings/stringize_macros.h" #include "base/strings/stringize_macros.h"
#include "base/thread_task_runner_handle.h" #include "base/thread_task_runner_handle.h"
...@@ -24,23 +22,14 @@ namespace { ...@@ -24,23 +22,14 @@ namespace {
// Returns NULL on failure, and logs an error message. // Returns NULL on failure, and logs an error message.
scoped_ptr<base::DictionaryValue> ConfigDictionaryFromMessage( scoped_ptr<base::DictionaryValue> ConfigDictionaryFromMessage(
const base::DictionaryValue& message) { const base::DictionaryValue& message) {
scoped_ptr<base::DictionaryValue> config_dict; scoped_ptr<base::DictionaryValue> result;
std::string config_str; const base::DictionaryValue* config_dict;
if (!message.GetString("config", &config_str)) { if (message.GetDictionary("config", &config_dict)) {
LOG(ERROR) << "'config' not found."; result.reset(config_dict->DeepCopy());
return config_dict.Pass(); } else {
} LOG(ERROR) << "'config' dictionary not found";
// TODO(lambroslambrou): Fix the webapp to embed the config dictionary
// directly into the request, rather than as a serialized JSON string.
scoped_ptr<base::Value> config(
base::JSONReader::Read(config_str, base::JSON_ALLOW_TRAILING_COMMAS));
if (!config || !config->IsType(base::Value::TYPE_DICTIONARY)) {
LOG(ERROR) << "Bad config parameter.";
return config_dict.Pass();
} }
config_dict.reset(reinterpret_cast<base::DictionaryValue*>(config.release())); return result.Pass();
return config_dict.Pass();
} }
} // namespace } // namespace
...@@ -61,8 +50,7 @@ NativeMessagingHost::NativeMessagingHost( ...@@ -61,8 +50,7 @@ NativeMessagingHost::NativeMessagingHost(
weak_ptr_ = weak_factory_.GetWeakPtr(); weak_ptr_ = weak_factory_.GetWeakPtr();
} }
NativeMessagingHost::~NativeMessagingHost() { NativeMessagingHost::~NativeMessagingHost() {}
}
void NativeMessagingHost::Start() { void NativeMessagingHost::Start() {
DCHECK(caller_task_runner_->BelongsToCurrentThread()); DCHECK(caller_task_runner_->BelongsToCurrentThread());
...@@ -198,8 +186,8 @@ bool NativeMessagingHost::ProcessUpdateDaemonConfig( ...@@ -198,8 +186,8 @@ bool NativeMessagingHost::ProcessUpdateDaemonConfig(
bool NativeMessagingHost::ProcessGetDaemonConfig( bool NativeMessagingHost::ProcessGetDaemonConfig(
const base::DictionaryValue& message, const base::DictionaryValue& message,
scoped_ptr<base::DictionaryValue> response) { scoped_ptr<base::DictionaryValue> response) {
daemon_controller_->GetConfig(base::Bind( daemon_controller_->GetConfig(
&NativeMessagingHost::SendConfigResponse, base::Bind(&NativeMessagingHost::SendConfigResponse,
base::Unretained(this), base::Passed(&response))); base::Unretained(this), base::Passed(&response)));
return true; return true;
} }
...@@ -207,8 +195,8 @@ bool NativeMessagingHost::ProcessGetDaemonConfig( ...@@ -207,8 +195,8 @@ bool NativeMessagingHost::ProcessGetDaemonConfig(
bool NativeMessagingHost::ProcessGetUsageStatsConsent( bool NativeMessagingHost::ProcessGetUsageStatsConsent(
const base::DictionaryValue& message, const base::DictionaryValue& message,
scoped_ptr<base::DictionaryValue> response) { scoped_ptr<base::DictionaryValue> response) {
daemon_controller_->GetUsageStatsConsent(base::Bind( daemon_controller_->GetUsageStatsConsent(
&NativeMessagingHost::SendUsageStatsConsentResponse, base::Bind(&NativeMessagingHost::SendUsageStatsConsentResponse,
base::Unretained(this), base::Passed(&response))); base::Unretained(this), base::Passed(&response)));
return true; return true;
} }
...@@ -237,8 +225,8 @@ bool NativeMessagingHost::ProcessStartDaemon( ...@@ -237,8 +225,8 @@ bool NativeMessagingHost::ProcessStartDaemon(
bool NativeMessagingHost::ProcessStopDaemon( bool NativeMessagingHost::ProcessStopDaemon(
const base::DictionaryValue& message, const base::DictionaryValue& message,
scoped_ptr<base::DictionaryValue> response) { scoped_ptr<base::DictionaryValue> response) {
daemon_controller_->Stop(base::Bind( daemon_controller_->Stop(
&NativeMessagingHost::SendAsyncResult, base::Unretained(this), base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this),
base::Passed(&response))); base::Passed(&response)));
return true; return true;
} }
...@@ -257,8 +245,8 @@ bool NativeMessagingHost::ProcessGetDaemonState( ...@@ -257,8 +245,8 @@ bool NativeMessagingHost::ProcessGetDaemonState(
void NativeMessagingHost::SendResponse( void NativeMessagingHost::SendResponse(
scoped_ptr<base::DictionaryValue> response) { scoped_ptr<base::DictionaryValue> response) {
if (!caller_task_runner_->BelongsToCurrentThread()) { if (!caller_task_runner_->BelongsToCurrentThread()) {
caller_task_runner_->PostTask(FROM_HERE, base::Bind( caller_task_runner_->PostTask(
&NativeMessagingHost::SendResponse, weak_ptr_, FROM_HERE, base::Bind(&NativeMessagingHost::SendResponse, weak_ptr_,
base::Passed(&response))); base::Passed(&response)));
return; return;
} }
...@@ -270,12 +258,7 @@ void NativeMessagingHost::SendResponse( ...@@ -270,12 +258,7 @@ void NativeMessagingHost::SendResponse(
void NativeMessagingHost::SendConfigResponse( void NativeMessagingHost::SendConfigResponse(
scoped_ptr<base::DictionaryValue> response, scoped_ptr<base::DictionaryValue> response,
scoped_ptr<base::DictionaryValue> config) { scoped_ptr<base::DictionaryValue> config) {
// TODO(lambroslambrou): Fix the web-app to accept the config dictionary response->Set("config", config.release());
// directly embedded in the response, rather than as serialized JSON. See
// http://crbug.com/232135.
std::string config_json;
base::JSONWriter::Write(config.get(), &config_json);
response->SetString("config", config_json);
SendResponse(response.Pass()); SendResponse(response.Pass());
} }
......
...@@ -138,14 +138,14 @@ remoting.HostController.prototype.start = function(hostPin, consent, callback) { ...@@ -138,14 +138,14 @@ remoting.HostController.prototype.start = function(hostPin, consent, callback) {
*/ */
function startHostWithHash(hostName, publicKey, privateKey, xhr, function startHostWithHash(hostName, publicKey, privateKey, xhr,
hostSecretHash) { hostSecretHash) {
var hostConfig = JSON.stringify({ var hostConfig = {
xmpp_login: remoting.identity.getCachedEmail(), xmpp_login: remoting.identity.getCachedEmail(),
oauth_refresh_token: remoting.oauth2.exportRefreshToken(), oauth_refresh_token: remoting.oauth2.exportRefreshToken(),
host_id: newHostId, host_id: newHostId,
host_name: hostName, host_name: hostName,
host_secret_hash: hostSecretHash, host_secret_hash: hostSecretHash,
private_key: privateKey private_key: privateKey
}); };
/** @param {remoting.HostController.AsyncResult} result */ /** @param {remoting.HostController.AsyncResult} result */
var onStartDaemon = function(result) { var onStartDaemon = function(result) {
onStarted(callback, result, hostName, publicKey); onStarted(callback, result, hostName, publicKey);
...@@ -245,29 +245,14 @@ remoting.HostController.prototype.stop = function(callback) { ...@@ -245,29 +245,14 @@ remoting.HostController.prototype.stop = function(callback) {
}; };
/** /**
* Parse a stringified host configuration and return it as a dictionary if it * Check the host configuration is valid (non-null, and contains both host_id
* is well-formed and contains both host_id and xmpp_login keys. null is * and xmpp_login keys).
* returned if either key is missing, or if the configuration is corrupt. * @param {Object} config The host configuration.
* @param {string} configStr The host configuration, JSON encoded to a string. * @return {boolean} True if it is valid.
* @return {Object.<string,string>|null} The host configuration.
*/ */
function parseHostConfig_(configStr) { function isHostConfigValid_(config) {
var config = /** @type {Object.<string,string>} */ jsonParseSafe(configStr); return !!config && typeof config['host_id'] == 'string' &&
if (config && typeof config['xmpp_login'] == 'string';
typeof config['host_id'] == 'string' &&
typeof config['xmpp_login'] == 'string') {
return config;
} else {
// {} means that host is not configured; '' means that the config file could
// not be read.
// TODO(jamiewalch): '' is expected if the host isn't installed, but should
// be reported as an error otherwise. Fix this once we have an event-based
// daemon state mechanism.
if (configStr != '{}' && configStr != '') {
console.error('Invalid getDaemonConfig response.');
}
}
return null;
} }
/** /**
...@@ -280,27 +265,27 @@ remoting.HostController.prototype.updatePin = function(newPin, callback) { ...@@ -280,27 +265,27 @@ remoting.HostController.prototype.updatePin = function(newPin, callback) {
/** @type {remoting.HostController} */ /** @type {remoting.HostController} */
var that = this; var that = this;
/** @param {string} configStr */ /** @param {Object} config */
function onConfig(configStr) { function onConfig(config) {
var config = parseHostConfig_(configStr); if (!isHostConfigValid_(config)) {
if (!config) {
callback(remoting.HostController.AsyncResult.FAILED); callback(remoting.HostController.AsyncResult.FAILED);
return; return;
} }
/** @type {string} */
var hostId = config['host_id']; var hostId = config['host_id'];
that.hostDispatcher_.getPinHash(hostId, newPin, updateDaemonConfigWithHash); that.hostDispatcher_.getPinHash(hostId, newPin, updateDaemonConfigWithHash);
} }
/** @param {string} pinHash */ /** @param {string} pinHash */
function updateDaemonConfigWithHash(pinHash) { function updateDaemonConfigWithHash(pinHash) {
var newConfig = JSON.stringify({ var newConfig = {
host_secret_hash: pinHash host_secret_hash: pinHash
}); };
that.hostDispatcher_.updateDaemonConfig(newConfig, callback); that.hostDispatcher_.updateDaemonConfig(newConfig, callback);
} }
// TODO(sergeyu): When crbug.com/121518 is fixed: replace this call // TODO(sergeyu): When crbug.com/121518 is fixed: replace this call
// with an upriveleged version if that is necessary. // with an unprivileged version if that is necessary.
this.hostDispatcher_.getDaemonConfig(onConfig); this.hostDispatcher_.getDaemonConfig(onConfig);
}; };
...@@ -322,12 +307,11 @@ remoting.HostController.prototype.getLocalHostState = function(onDone) { ...@@ -322,12 +307,11 @@ remoting.HostController.prototype.getLocalHostState = function(onDone) {
remoting.HostController.prototype.getLocalHostId = function(onDone) { remoting.HostController.prototype.getLocalHostId = function(onDone) {
/** @type {remoting.HostController} */ /** @type {remoting.HostController} */
var that = this; var that = this;
/** @param {string} configStr */ /** @param {Object} config */
function onConfig(configStr) { function onConfig(config) {
var config = parseHostConfig_(configStr);
var hostId = null; var hostId = null;
if (config) { if (isHostConfigValid_(config)) {
hostId = config['host_id']; hostId = /** @type {string} */ config['host_id'];
} }
onDone(hostId); onDone(hostId);
}; };
......
...@@ -128,7 +128,7 @@ remoting.HostDispatcher.prototype.generateKeyPair = function(callback) { ...@@ -128,7 +128,7 @@ remoting.HostDispatcher.prototype.generateKeyPair = function(callback) {
}; };
/** /**
* @param {string} config * @param {Object} config
* @param {function(remoting.HostController.AsyncResult):void} callback * @param {function(remoting.HostController.AsyncResult):void} callback
* @return {void} * @return {void}
*/ */
...@@ -142,17 +142,34 @@ remoting.HostDispatcher.prototype.updateDaemonConfig = function(config, ...@@ -142,17 +142,34 @@ remoting.HostDispatcher.prototype.updateDaemonConfig = function(config,
this.nativeMessagingHost_.updateDaemonConfig(config, callback); this.nativeMessagingHost_.updateDaemonConfig(config, callback);
break; break;
case remoting.HostDispatcher.State.NPAPI: case remoting.HostDispatcher.State.NPAPI:
this.npapiHost_.updateDaemonConfig(config, callback); this.npapiHost_.updateDaemonConfig(JSON.stringify(config), callback);
break; break;
} }
}; };
/** /**
* @param {function(string):void} callback * @param {function(Object):void} callback
* @return {void} * @return {void}
*/ */
remoting.HostDispatcher.prototype.getDaemonConfig = function(callback) { remoting.HostDispatcher.prototype.getDaemonConfig = function(callback) {
/**
* Converts the config string from the NPAPI plugin to an Object, to pass to
* |callback|.
* @param {string} configStr
* @return {void}
*/
function callbackForNpapi(configStr) {
var config = null;
try {
config = JSON.parse(configStr);
} catch (err) {}
if (typeof(config) != 'object') {
// TODO(lambroslambrou): Call error handler here when that's implemented.
config = null;
}
callback(/** @type {Object} */ (config));
}
switch (this.state_) { switch (this.state_) {
case remoting.HostDispatcher.State.UNKNOWN: case remoting.HostDispatcher.State.UNKNOWN:
this.pendingRequests_.push(this.getDaemonConfig.bind(this, callback)); this.pendingRequests_.push(this.getDaemonConfig.bind(this, callback));
...@@ -161,7 +178,7 @@ remoting.HostDispatcher.prototype.getDaemonConfig = function(callback) { ...@@ -161,7 +178,7 @@ remoting.HostDispatcher.prototype.getDaemonConfig = function(callback) {
this.nativeMessagingHost_.getDaemonConfig(callback); this.nativeMessagingHost_.getDaemonConfig(callback);
break; break;
case remoting.HostDispatcher.State.NPAPI: case remoting.HostDispatcher.State.NPAPI:
this.npapiHost_.getDaemonConfig(callback); this.npapiHost_.getDaemonConfig(callbackForNpapi);
break; break;
} }
}; };
...@@ -204,7 +221,7 @@ remoting.HostDispatcher.prototype.getUsageStatsConsent = function(callback) { ...@@ -204,7 +221,7 @@ remoting.HostDispatcher.prototype.getUsageStatsConsent = function(callback) {
}; };
/** /**
* @param {string} config * @param {Object} config
* @param {boolean} consent * @param {boolean} consent
* @param {function(remoting.HostController.AsyncResult):void} callback * @param {function(remoting.HostController.AsyncResult):void} callback
* @return {void} * @return {void}
...@@ -220,7 +237,7 @@ remoting.HostDispatcher.prototype.startDaemon = function(config, consent, ...@@ -220,7 +237,7 @@ remoting.HostDispatcher.prototype.startDaemon = function(config, consent,
this.nativeMessagingHost_.startDaemon(config, consent, callback); this.nativeMessagingHost_.startDaemon(config, consent, callback);
break; break;
case remoting.HostDispatcher.State.NPAPI: case remoting.HostDispatcher.State.NPAPI:
this.npapiHost_.startDaemon(config, consent, callback); this.npapiHost_.startDaemon(JSON.stringify(config), consent, callback);
break; break;
} }
}; };
......
...@@ -252,7 +252,7 @@ remoting.HostNativeMessaging.prototype.onIncomingMessage_ = function(message) { ...@@ -252,7 +252,7 @@ remoting.HostNativeMessaging.prototype.onIncomingMessage_ = function(message) {
case 'getDaemonConfigResponse': case 'getDaemonConfigResponse':
/** @type {*} */ /** @type {*} */
var config = message['config']; var config = message['config'];
if (checkType_('config', config, 'string')) { if (checkType_('config', config, 'object')) {
callback(config); callback(config);
} }
break; break;
...@@ -372,7 +372,7 @@ remoting.HostNativeMessaging.prototype.generateKeyPair = function(callback) { ...@@ -372,7 +372,7 @@ remoting.HostNativeMessaging.prototype.generateKeyPair = function(callback) {
* includes these parameters. Changes take effect before the callback * includes these parameters. Changes take effect before the callback
* is called. * is called.
* *
* @param {string} config The new config parameters, JSON encoded dictionary. * @param {Object} config The new config parameters.
* @param {function(remoting.HostController.AsyncResult):void} callback * @param {function(remoting.HostController.AsyncResult):void} callback
* Callback to be called when finished. * Callback to be called when finished.
* @return {void} Nothing. * @return {void} Nothing.
...@@ -389,7 +389,7 @@ remoting.HostNativeMessaging.prototype.updateDaemonConfig = ...@@ -389,7 +389,7 @@ remoting.HostNativeMessaging.prototype.updateDaemonConfig =
* Loads daemon config. The config is passed as a JSON formatted string to the * Loads daemon config. The config is passed as a JSON formatted string to the
* callback. * callback.
* *
* @param {function(string):void} callback Callback. * @param {function(Object):void} callback Callback.
* @return {void} Nothing. * @return {void} Nothing.
*/ */
remoting.HostNativeMessaging.prototype.getDaemonConfig = function(callback) { remoting.HostNativeMessaging.prototype.getDaemonConfig = function(callback) {
...@@ -425,7 +425,7 @@ remoting.HostNativeMessaging.prototype.getUsageStatsConsent = ...@@ -425,7 +425,7 @@ remoting.HostNativeMessaging.prototype.getUsageStatsConsent =
/** /**
* Starts the daemon process with the specified configuration. * Starts the daemon process with the specified configuration.
* *
* @param {string} config Host configuration. * @param {Object} config Host configuration.
* @param {boolean} consent Consent to report crash dumps. * @param {boolean} consent Consent to report crash dumps.
* @param {function(remoting.HostController.AsyncResult):void} callback * @param {function(remoting.HostController.AsyncResult):void} callback
* Callback. * Callback.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment