|  | // Copyright 2014 The Chromium OS 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 <iostream>  // NOLINT(readability/streams) | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <sysexits.h> | 
|  |  | 
|  | #include <base/command_line.h> | 
|  | #include <base/logging.h> | 
|  | #include <base/memory/ref_counted.h> | 
|  | #include <base/values.h> | 
|  | #include <chromeos/any.h> | 
|  | #include <chromeos/data_encoding.h> | 
|  | #include <chromeos/dbus/data_serialization.h> | 
|  | #include <chromeos/dbus/dbus_method_invoker.h> | 
|  | #include <chromeos/errors/error.h> | 
|  | #include <chromeos/variant_dictionary.h> | 
|  | #include <dbus/bus.h> | 
|  | #include <dbus/message.h> | 
|  | #include <dbus/object_proxy.h> | 
|  | #include <dbus/object_manager.h> | 
|  | #include <dbus/values_util.h> | 
|  |  | 
|  | #include "buffet/libbuffet/dbus_constants.h" | 
|  |  | 
|  | using namespace buffet::dbus_constants;  // NOLINT(build/namespaces) | 
|  |  | 
|  | using chromeos::dbus_utils::CallMethodAndBlock; | 
|  | using chromeos::dbus_utils::CallMethodAndBlockWithTimeout; | 
|  | using chromeos::dbus_utils::ExtractMethodCallResults; | 
|  | using chromeos::VariantDictionary; | 
|  | using chromeos::ErrorPtr; | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | void usage() { | 
|  | std::cerr << "Possible commands:" << std::endl; | 
|  | std::cerr << "  " << kManagerTestMethod << " <message>" << std::endl; | 
|  | std::cerr << "  " << kManagerCheckDeviceRegistered << std::endl; | 
|  | std::cerr << "  " << kManagerGetDeviceInfo << std::endl; | 
|  | std::cerr << "  " << kManagerStartRegisterDevice | 
|  | << " param1 = val1¶m2 = val2..." << std::endl; | 
|  | std::cerr << "  " << kManagerFinishRegisterDevice | 
|  | << " device_id" << std::endl; | 
|  | std::cerr << "  " << kManagerAddCommand | 
|  | << " '{\"name\":\"command_name\",\"parameters\":{}}'" | 
|  | << std::endl; | 
|  | std::cerr << "  " << kManagerUpdateStateMethod | 
|  | << " prop_name prop_value" << std::endl; | 
|  | std::cerr << "  " << dbus::kObjectManagerGetManagedObjects << std::endl; | 
|  | } | 
|  |  | 
|  | class BuffetHelperProxy { | 
|  | public: | 
|  | int Init() { | 
|  | dbus::Bus::Options options; | 
|  | options.bus_type = dbus::Bus::SYSTEM; | 
|  | bus_ = new dbus::Bus(options); | 
|  | manager_proxy_ = bus_->GetObjectProxy( | 
|  | kServiceName, | 
|  | dbus::ObjectPath(kManagerServicePath)); | 
|  | root_proxy_ = bus_->GetObjectProxy( | 
|  | kServiceName, | 
|  | dbus::ObjectPath(kRootServicePath)); | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | int CallTestMethod(const CommandLine::StringVector& args) { | 
|  | std::string message; | 
|  | if (!args.empty()) | 
|  | message = args.front(); | 
|  |  | 
|  | ErrorPtr error; | 
|  | auto response = CallMethodAndBlock( | 
|  | manager_proxy_, | 
|  | kManagerInterface, kManagerTestMethod, &error, | 
|  | message); | 
|  | std::string response_message; | 
|  | if (!response || | 
|  | !ExtractMethodCallResults(response.get(), &error, &response_message)) { | 
|  | std::cout << "Failed to receive a response:" | 
|  | << error->GetMessage() << std::endl; | 
|  | return EX_UNAVAILABLE; | 
|  | } | 
|  |  | 
|  | std::cout << "Received a response: " << response_message << std::endl; | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | int CallManagerCheckDeviceRegistered(const CommandLine::StringVector& args) { | 
|  | if (!args.empty()) { | 
|  | std::cerr << "Invalid number of arguments for " | 
|  | << "Manager." << kManagerCheckDeviceRegistered << std::endl; | 
|  | usage(); | 
|  | return EX_USAGE; | 
|  | } | 
|  |  | 
|  | ErrorPtr error; | 
|  | auto response = CallMethodAndBlock( | 
|  | manager_proxy_, | 
|  | kManagerInterface, kManagerCheckDeviceRegistered, &error); | 
|  | std::string device_id; | 
|  | if (!response || | 
|  | !ExtractMethodCallResults(response.get(), &error, &device_id)) { | 
|  | std::cout << "Failed to receive a response:" | 
|  | << error->GetMessage() << std::endl; | 
|  | return EX_UNAVAILABLE; | 
|  | } | 
|  |  | 
|  | std::cout << "Device ID: " | 
|  | << (device_id.empty() ? std::string("<unregistered>") : device_id) | 
|  | << std::endl; | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | int CallManagerGetDeviceInfo(const CommandLine::StringVector& args) { | 
|  | if (!args.empty()) { | 
|  | std::cerr << "Invalid number of arguments for " | 
|  | << "Manager." << kManagerGetDeviceInfo << std::endl; | 
|  | usage(); | 
|  | return EX_USAGE; | 
|  | } | 
|  |  | 
|  | ErrorPtr error; | 
|  | auto response = CallMethodAndBlock( | 
|  | manager_proxy_, kManagerInterface, kManagerGetDeviceInfo, &error); | 
|  | std::string device_info; | 
|  | if (!response || | 
|  | !ExtractMethodCallResults(response.get(), &error, &device_info)) { | 
|  | std::cout << "Failed to receive a response:" | 
|  | << error->GetMessage() << std::endl; | 
|  | return EX_UNAVAILABLE; | 
|  | } | 
|  |  | 
|  | std::cout << "Device Info: " | 
|  | << (device_info.empty() ? std::string("<unregistered>") : device_info) | 
|  | << std::endl; | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | int CallManagerStartRegisterDevice(const CommandLine::StringVector& args) { | 
|  | if (args.size() > 1) { | 
|  | std::cerr << "Invalid number of arguments for " | 
|  | << "Manager." << kManagerStartRegisterDevice << std::endl; | 
|  | usage(); | 
|  | return EX_USAGE; | 
|  | } | 
|  |  | 
|  | VariantDictionary params; | 
|  | if (!args.empty()) { | 
|  | auto key_values = chromeos::data_encoding::WebParamsDecode(args.front()); | 
|  | for (const auto& pair : key_values) { | 
|  | params.insert(std::make_pair(pair.first, chromeos::Any(pair.second))); | 
|  | } | 
|  | } | 
|  |  | 
|  | ErrorPtr error; | 
|  | static const int timeout_ms = 3000; | 
|  | auto response = CallMethodAndBlockWithTimeout( | 
|  | timeout_ms, | 
|  | manager_proxy_, | 
|  | kManagerInterface, kManagerStartRegisterDevice, &error, | 
|  | params); | 
|  | std::string info; | 
|  | if (!response || | 
|  | !ExtractMethodCallResults(response.get(), &error, &info)) { | 
|  | std::cout << "Failed to receive a response:" | 
|  | << error->GetMessage() << std::endl; | 
|  | return EX_UNAVAILABLE; | 
|  | } | 
|  |  | 
|  | std::cout << "Registration started: " << info << std::endl; | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | int CallManagerFinishRegisterDevice(const CommandLine::StringVector& args) { | 
|  | if (args.size() > 1) { | 
|  | std::cerr << "Invalid number of arguments for " | 
|  | << "Manager." << kManagerFinishRegisterDevice << std::endl; | 
|  | usage(); | 
|  | return EX_USAGE; | 
|  | } | 
|  |  | 
|  | ErrorPtr error; | 
|  | std::string user_auth_code; | 
|  | if (!args.empty()) { user_auth_code = args.front(); } | 
|  | static const int timeout_ms = 10000; | 
|  | auto response = CallMethodAndBlockWithTimeout( | 
|  | timeout_ms, | 
|  | manager_proxy_, | 
|  | kManagerInterface, kManagerFinishRegisterDevice, &error, | 
|  | user_auth_code); | 
|  | std::string device_id; | 
|  | if (!response || | 
|  | !ExtractMethodCallResults(response.get(), &error, &device_id)) { | 
|  | std::cout << "Failed to receive a response:" | 
|  | << error->GetMessage() << std::endl; | 
|  | return EX_UNAVAILABLE; | 
|  | } | 
|  |  | 
|  | std::cout << "Device ID is " | 
|  | << (device_id.empty() ? std::string("<unregistered>") : device_id) | 
|  | << std::endl; | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | int CallManagerUpdateState(const CommandLine::StringVector& args) { | 
|  | if (args.size() != 2) { | 
|  | std::cerr << "Invalid number of arguments for " | 
|  | << "Manager." << kManagerUpdateStateMethod << std::endl; | 
|  | usage(); | 
|  | return EX_USAGE; | 
|  | } | 
|  |  | 
|  | ErrorPtr error; | 
|  | VariantDictionary property_set{{args.front(), args.back()}}; | 
|  | auto response = CallMethodAndBlock( | 
|  | manager_proxy_, | 
|  | kManagerInterface, kManagerUpdateStateMethod, &error, | 
|  | property_set); | 
|  | if (!response || !ExtractMethodCallResults(response.get(), &error)) { | 
|  | std::cout << "Failed to receive a response:" | 
|  | << error->GetMessage() << std::endl; | 
|  | return EX_UNAVAILABLE; | 
|  | } | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | int CallManagerAddCommand(const CommandLine::StringVector& args) { | 
|  | if (args.size() != 1) { | 
|  | std::cerr << "Invalid number of arguments for " | 
|  | << "Manager." << kManagerAddCommand << std::endl; | 
|  | usage(); | 
|  | return EX_USAGE; | 
|  | } | 
|  |  | 
|  | ErrorPtr error; | 
|  | auto response = CallMethodAndBlock( | 
|  | manager_proxy_, | 
|  | kManagerInterface, kManagerAddCommand, &error, | 
|  | args.front()); | 
|  | if (!response || !ExtractMethodCallResults(response.get(), &error)) { | 
|  | std::cout << "Failed to receive a response:" | 
|  | << error->GetMessage() << std::endl; | 
|  | return EX_UNAVAILABLE; | 
|  | } | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | int CallRootGetManagedObjects(const CommandLine::StringVector& args) { | 
|  | if (!args.empty()) { | 
|  | std::cerr << "Invalid number of arguments for " | 
|  | << dbus::kObjectManagerGetManagedObjects << std::endl; | 
|  | usage(); | 
|  | return EX_USAGE; | 
|  | } | 
|  |  | 
|  | ErrorPtr error; | 
|  | auto response = CallMethodAndBlock( | 
|  | manager_proxy_, | 
|  | dbus::kObjectManagerInterface, dbus::kObjectManagerGetManagedObjects, | 
|  | &error); | 
|  | if (!response) { | 
|  | std::cout << "Failed to receive a response:" | 
|  | << error->GetMessage() << std::endl; | 
|  | return EX_UNAVAILABLE; | 
|  | } | 
|  | std::cout << response->ToString() << std::endl; | 
|  | return EX_OK; | 
|  | } | 
|  |  | 
|  | private: | 
|  | scoped_refptr<dbus::Bus> bus_; | 
|  | dbus::ObjectProxy* manager_proxy_{nullptr}; | 
|  | dbus::ObjectProxy* root_proxy_{nullptr}; | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | int main(int argc, char** argv) { | 
|  | CommandLine::Init(argc, argv); | 
|  | CommandLine* cl = CommandLine::ForCurrentProcess(); | 
|  | CommandLine::StringVector args = cl->GetArgs(); | 
|  | if (args.empty()) { | 
|  | usage(); | 
|  | return EX_USAGE; | 
|  | } | 
|  |  | 
|  | // Pop the command off of the args list. | 
|  | std::string command = args.front(); | 
|  | args.erase(args.begin()); | 
|  | int err = EX_USAGE; | 
|  | BuffetHelperProxy helper; | 
|  | err = helper.Init(); | 
|  | if (err) { | 
|  | std::cerr << "Error initializing proxies." << std::endl; | 
|  | return err; | 
|  | } | 
|  |  | 
|  | if (command.compare(kManagerTestMethod) == 0) { | 
|  | err = helper.CallTestMethod(args); | 
|  | } else if (command.compare(kManagerCheckDeviceRegistered) == 0 || | 
|  | command.compare("cr") == 0) { | 
|  | err = helper.CallManagerCheckDeviceRegistered(args); | 
|  | } else if (command.compare(kManagerGetDeviceInfo) == 0 || | 
|  | command.compare("di") == 0) { | 
|  | err = helper.CallManagerGetDeviceInfo(args); | 
|  | } else if (command.compare(kManagerStartRegisterDevice) == 0 || | 
|  | command.compare("sr") == 0) { | 
|  | err = helper.CallManagerStartRegisterDevice(args); | 
|  | } else if (command.compare(kManagerFinishRegisterDevice) == 0 || | 
|  | command.compare("fr") == 0) { | 
|  | err = helper.CallManagerFinishRegisterDevice(args); | 
|  | } else if (command.compare(kManagerUpdateStateMethod) == 0 || | 
|  | command.compare("us") == 0) { | 
|  | err = helper.CallManagerUpdateState(args); | 
|  | } else if (command.compare(kManagerAddCommand) == 0 || | 
|  | command.compare("ac") == 0) { | 
|  | err = helper.CallManagerAddCommand(args); | 
|  | } else if (command.compare(dbus::kObjectManagerGetManagedObjects) == 0) { | 
|  | err = helper.CallRootGetManagedObjects(args); | 
|  | } else { | 
|  | std::cerr << "Unknown command: " << command << std::endl; | 
|  | usage(); | 
|  | } | 
|  |  | 
|  | if (err) { | 
|  | std::cerr << "Done, with errors." << std::endl; | 
|  | } else { | 
|  | std::cout << "Done." << std::endl; | 
|  | } | 
|  | return err; | 
|  | } |