Connectivity Diagnostics Private API

Proposal:https://docs.google.com/a/chromium.org/document/d/1U_exKvPmT4AXyqFuHgVBbgBZ2RAKNBjk6MwSPcceWXw/edit

Overview
We’d like to have a set of APIs useful for diagnostics tools, and initially, an API that can be used to replicate ping and traceroute functionality.

Use cases
The sendPacket API is used by a diagnostics tool to find problems in the network configuration of an environment and determine latency issues.

BUG=250851

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208026 0039d316-1c4b-4281-b951-d872f2087c98
parent 19fce418
// Copyright 2013 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.
#include "chrome/browser/extensions/api/diagnostics/diagnostics_api.h"
namespace SendPacket = extensions::api::diagnostics::SendPacket;
namespace {
const char kErrorPingNotImplemented[] = "Not implemented";
const char kErrorPingFailed[] = "Failed to send ping packet";
}
namespace extensions {
DiagnosticsSendPacketFunction::DiagnosticsSendPacketFunction() {}
DiagnosticsSendPacketFunction::~DiagnosticsSendPacketFunction() {}
bool DiagnosticsSendPacketFunction::Prepare() {
parameters_ = SendPacket::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(parameters_.get());
return true;
}
bool DiagnosticsSendPacketFunction::Respond() {
return error_.empty();
}
void DiagnosticsSendPacketFunction::OnCompleted(
SendPacketResultCode result_code,
const std::string& ip,
double latency) {
switch (result_code) {
case SEND_PACKET_OK: {
extensions::api::diagnostics::SendPacketResult result;
result.ip = ip;
result.latency = latency;
results_ = SendPacket::Results::Create(result);
break;
}
case SEND_PACKET_NOT_IMPLEMENTED:
SetError(kErrorPingNotImplemented);
break;
case SEND_PACKET_FAILED:
SetError(kErrorPingFailed);
break;
}
AsyncWorkCompleted();
}
} // namespace extensions
// Copyright 2013 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.
#ifndef CHROME_BROWSER_EXTENSIONS_API_DIAGNOSTICS_DIAGNOSTICS_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_DIAGNOSTICS_DIAGNOSTICS_API_H_
#include <string>
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/api/api_function.h"
#include "chrome/common/extensions/api/diagnostics.h"
namespace extensions {
class DiagnosticsSendPacketFunction : public AsyncApiFunction {
public:
// Result code for sending packet. Platform specific AsyncWorkStart() will
// finish with this ResultCode so we can maximize shared code.
enum SendPacketResultCode {
// Ping packed is sent and ICMP reply is received before time out.
SEND_PACKET_OK,
// Not implemented on the platform.
SEND_PACKET_NOT_IMPLEMENTED,
// The ping operation failed because of timeout or network unreachable.
SEND_PACKET_FAILED,
};
DECLARE_EXTENSION_FUNCTION("diagnostics.sendPacket",
DIAGNOSTICS_SENDPACKET);
DiagnosticsSendPacketFunction();
protected:
virtual ~DiagnosticsSendPacketFunction();
// AsyncApiFunction:
virtual bool Prepare() OVERRIDE;
// This methods will be implemented differently on different platforms.
virtual void AsyncWorkStart() OVERRIDE;
virtual bool Respond() OVERRIDE;
private:
void SendPingPacket();
void OnCompleted(SendPacketResultCode result_code,
const std::string& ip,
double latency);
scoped_ptr<extensions::api::diagnostics::SendPacket::Params>
parameters_;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_DIAGNOSTICS_DIAGNOSTICS_API_H_
// Copyright 2013 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.
#include "chrome/browser/extensions/api/diagnostics/diagnostics_api.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/json/json_reader.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon_client.h"
namespace extensions {
namespace {
const char kCount[] = "count";
const char kDefaultCount[] = "1";
const char kTTL[] = "ttl";
const char kTimeout[] = "timeout";
const char kSize[] = "size";
typedef base::Callback<void(
DiagnosticsSendPacketFunction::SendPacketResultCode result_code,
const std::string& ip,
double latency)>
SendPacketCallback;
bool ParseResult(const std::string& status,
std::string* ip,
double* latency) {
// Parses the result and returns IP and latency.
scoped_ptr<base::Value> parsed_value(base::JSONReader::Read(status));
if (!parsed_value)
return false;
base::DictionaryValue* result = NULL;
if (!parsed_value->GetAsDictionary(&result) || result->size() != 1)
return false;
// Returns the first item.
base::DictionaryValue::Iterator iterator(*result);
const base::DictionaryValue* info;
if (!iterator.value().GetAsDictionary(&info))
return false;
if (info->GetDouble("avg", latency))
return false;
*ip = iterator.key();
return true;
}
void OnTestICMPCompleted(
const SendPacketCallback& callback,
bool succeeded,
const std::string& status) {
std::string ip;
double latency;
if (!succeeded || !ParseResult(status, &ip, &latency)) {
callback.Run(DiagnosticsSendPacketFunction::SEND_PACKET_FAILED, "", 0.0);
} else {
callback.Run(DiagnosticsSendPacketFunction::SEND_PACKET_OK,
ip,
latency);
}
}
} // namespace
void DiagnosticsSendPacketFunction::AsyncWorkStart() {
std::map<std::string, std::string> config;
config[kCount] = kDefaultCount;
if (parameters_->options.ttl)
config[kTTL] = base::IntToString(*parameters_->options.ttl);
if (parameters_->options.timeout)
config[kTimeout] = base::IntToString(*parameters_->options.timeout);
if (parameters_->options.size)
config[kSize] = base::IntToString(*parameters_->options.size);
chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
TestICMPWithOptions(
parameters_->options.ip, config,
base::Bind(
OnTestICMPCompleted,
base::Bind(&DiagnosticsSendPacketFunction::OnCompleted, this)));
}
} // namespace extensions
// Copyright 2013 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.
#include "chrome/browser/extensions/api/diagnostics/diagnostics_api.h"
namespace extensions {
void DiagnosticsSendPacketFunction::AsyncWorkStart() {
OnCompleted(SEND_PACKET_NOT_IMPLEMENTED, "", 0.0);
}
} // namespace extensions
......@@ -553,6 +553,7 @@ enum HistogramValue {
FEEDBACKPRIVATE_GETSYSTEMINFORMATION,
FEEDBACKPRIVATE_SENDFEEDBACK,
EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_INSERTTEXT,
DIAGNOSTICS_SENDPACKET,
ENUM_BOUNDARY // Last entry: Add new entries above.
};
......
......@@ -336,6 +336,10 @@
'browser/extensions/api/permissions/permissions_api.h',
'browser/extensions/api/permissions/permissions_api_helpers.cc',
'browser/extensions/api/permissions/permissions_api_helpers.h',
'browser/extensions/api/diagnostics/diagnostics_api.cc',
'browser/extensions/api/diagnostics/diagnostics_api.h',
'browser/extensions/api/diagnostics/diagnostics_api_nonchromeos.cc',
'browser/extensions/api/diagnostics/diagnostics_api_chromeos.cc',
'browser/extensions/api/power/power_api.cc',
'browser/extensions/api/power/power_api.h',
'browser/extensions/api/power/power_api_manager.cc',
......@@ -794,6 +798,7 @@
'sources!': [
'browser/extensions/api/audio/audio_service.cc',
'browser/extensions/api/feedback_private/feedback_service_nonchromeos.cc',
'browser/extensions/api/diagnostics/diagnostics_api_nonchromeos.cc',
'browser/extensions/default_apps.cc',
'browser/extensions/default_apps.h',
],
......
......@@ -121,6 +121,11 @@
"dependencies": ["permission:developerPrivate"],
"contexts": ["blessed_extension"]
},
"diagnostics": {
"dependencies": ["permission:diagnostics"],
"extension_types": ["platform_app"],
"contexts": ["blessed_extension"]
},
"dial": {
"dependencies": ["permission:dial"],
"contexts": ["blessed_extension"]
......
......@@ -138,6 +138,21 @@
"channel": "stable",
"extension_types": ["extension", "packaged_app"]
},
"diagnostics": [
{
"channel": "dev",
"extension_types": ["platform_app"]
},
{
"channel": "stable",
"extension_types": ["platform_app"],
"whitelist": [
"mlocfejafidcakdddnndjdngfmncfbeg", // CCD Development
"ganomidahfnpdchomfgdoppjmmedlhia", // CCD Testing
"eemlkeanncmjljgehlbplemhmdmalhdc" // CCD Release
]
}
],
"debugger": {
"channel": "stable",
"extension_types": ["extension", "packaged_app"]
......
......@@ -37,6 +37,7 @@
'cookies.json',
'debugger.json',
'developer_private.idl',
'diagnostics.idl',
'dial.idl',
'downloads.idl',
'echo_private.json',
......
// Copyright 2013 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.
namespace diagnostics {
dictionary SendPacketOptions {
// Target IP address.
DOMString ip;
// Packet time to live value. If omitted, the system default value will be
// used.
long? ttl;
// Packet timeout in seconds. If omitted, the system default value will be
// used.
long? timeout;
// Size of the payload. If omitted, the system default value will be used.
long? size;
};
dictionary SendPacketResult {
// The IP of the host which we recieves the ICMP reply from.
// The IP may differs from our target IP if the packet's ttl is used up.
DOMString ip;
// Latency in millisenconds.
double latency;
};
callback SendPacketCallback = void(SendPacketResult result);
interface Functions {
// Send a packet of the given type with the given parameters.
static void sendPacket(SendPacketOptions options,
SendPacketCallback callback);
};
};
......@@ -59,6 +59,7 @@ class APIPermission {
kContentSettings,
kContextMenus,
kCookie,
kDiagnostics,
kDial,
kDebugger,
kDeclarative,
......
......@@ -149,6 +149,8 @@ std::vector<APIPermissionInfo*> ChromeAPIPermissions::GetAllPermissions()
APIPermissionInfo::kFlagCannotBeOptional },
{ APIPermission::kDeveloperPrivate, "developerPrivate",
APIPermissionInfo::kFlagCannotBeOptional },
{ APIPermission::kDiagnostics, "diagnostics",
APIPermissionInfo::kFlagCannotBeOptional },
{ APIPermission::kDial, "dial", APIPermissionInfo::kFlagCannotBeOptional },
{ APIPermission::kDownloadsInternal, "downloadsInternal" },
{ APIPermission::kFileBrowserHandlerInternal, "fileBrowserHandlerInternal",
......
......@@ -632,6 +632,7 @@ TEST(PermissionsTest, PermissionMessages) {
skip.insert(APIPermission::kAudio);
skip.insert(APIPermission::kBrowsingData);
skip.insert(APIPermission::kContextMenus);
skip.insert(APIPermission::kDiagnostics);
skip.insert(APIPermission::kFontSettings);
skip.insert(APIPermission::kFullscreen);
skip.insert(APIPermission::kIdle);
......
......@@ -346,6 +346,39 @@ class DebugDaemonClientImpl : public DebugDaemonClient {
callback));
}
virtual void TestICMPWithOptions(
const std::string& ip_address,
const std::map<std::string, std::string>& options,
const TestICMPCallback& callback) OVERRIDE {
dbus::MethodCall method_call(debugd::kDebugdInterface,
debugd::kTestICMPWithOptions);
dbus::MessageWriter writer(&method_call);
dbus::MessageWriter sub_writer(NULL);
dbus::MessageWriter elem_writer(NULL);
// Write the host.
writer.AppendString(ip_address);
// Write the options.
writer.OpenArray("{ss}", &sub_writer);
std::map<std::string, std::string>::const_iterator it;
for (it = options.begin(); it != options.end(); ++it) {
sub_writer.OpenDictEntry(&elem_writer);
elem_writer.AppendString(it->first);
elem_writer.AppendString(it->second);
sub_writer.CloseContainer(&elem_writer);
}
writer.CloseContainer(&sub_writer);
// Call the function.
debugdaemon_proxy_->CallMethod(
&method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::Bind(&DebugDaemonClientImpl::OnTestICMP,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
private:
// Called to check descriptor validity on a thread where i/o is permitted.
static void CheckValidity(dbus::FileDescriptor* file_descriptor) {
......@@ -573,22 +606,22 @@ class DebugDaemonClientStubImpl : public DebugDaemonClient {
const GetRoutesCallback& callback) OVERRIDE {
std::vector<std::string> empty;
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, false, empty));
base::Bind(callback, false, empty));
}
virtual void GetNetworkStatus(const GetNetworkStatusCallback& callback)
OVERRIDE {
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, false, ""));
base::Bind(callback, false, ""));
}
virtual void GetModemStatus(const GetModemStatusCallback& callback)
OVERRIDE {
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, false, ""));
base::Bind(callback, false, ""));
}
virtual void GetNetworkInterfaces(
const GetNetworkInterfacesCallback& callback) OVERRIDE {
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, false, ""));
base::Bind(callback, false, ""));
}
virtual void GetPerfData(uint32_t duration,
const GetPerfDataCallback& callback) OVERRIDE {
......@@ -599,20 +632,29 @@ class DebugDaemonClientStubImpl : public DebugDaemonClient {
virtual void GetAllLogs(const GetLogsCallback& callback) OVERRIDE {
std::map<std::string, std::string> empty;
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, false, empty));
base::Bind(callback, false, empty));
}
virtual void GetUserLogFiles(const GetLogsCallback& callback) OVERRIDE {
std::map<std::string, std::string> user_logs;
user_logs["preferences"] = "Preferences";
user_logs["invalid_file"] = "Invalid File";
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, true, user_logs));
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(callback, true, user_logs));
}
virtual void TestICMP(const std::string& ip_address,
const TestICMPCallback& callback) OVERRIDE {
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, false, ""));
base::Bind(callback, false, ""));
}
virtual void TestICMPWithOptions(
const std::string& ip_address,
const std::map<std::string, std::string>& options,
const TestICMPCallback& callback) OVERRIDE {
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, false, ""));
}
};
......
......@@ -127,6 +127,13 @@ class CHROMEOS_EXPORT DebugDaemonClient {
virtual void TestICMP(const std::string& ip_address,
const TestICMPCallback& callback) = 0;
// Tests ICMP connectivity to a specified host. The |ip_address| contains the
// IPv4 or IPv6 address of the host, for example "8.8.8.8".
virtual void TestICMPWithOptions(
const std::string& ip_address,
const std::map<std::string, std::string>& options,
const TestICMPCallback& callback) = 0;
// Factory function, creates a new instance and returns ownership.
// For normal usage, access the singleton via DBusThreadManager::Get().
static DebugDaemonClient* Create(DBusClientImplementationType type,
......
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