12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cloud_print/service/win/setup_listener.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <atlbase.h> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <atlsecurity.h> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/guid.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_reader.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/service/win/service_utils.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_channel.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char SetupListener::kXpsAvailableJsonValueName[] = "xps_available"; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char SetupListener::kChromePathJsonValueName[] = "chrome_path"; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char SetupListener::kPrintersJsonValueName[] = "printers"; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char SetupListener::kUserDataDirJsonValueName[] = "user_data_dir"; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char SetupListener::kUserNameJsonValueName[] = "user_name"; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const wchar_t SetupListener::kSetupPipeName[] = 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) L"\\\\.\\pipe\\CloudPrintServiceSetup"; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)SetupListener::SetupListener(const base::string16& user) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : done_event_(new base::WaitableEvent(true, false)), 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ipc_thread_(new base::Thread("ipc_thread")), 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) succeded_(false), 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_xps_available_(false) { 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ipc_thread_->StartWithOptions( 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ipc_thread_->message_loop()->PostTask( 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&SetupListener::Connect, base::Unretained(this), user)); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SetupListener::~SetupListener() { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ipc_thread_->message_loop()->PostTask(FROM_HERE, 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SetupListener::Disconnect, 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ipc_thread_->Stop(); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SetupListener::OnMessageReceived(const IPC::Message& msg) { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PickleIterator iter(msg); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string json_string; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!iter.ReadString(&json_string)) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::DictionaryValue* dictionary = NULL; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!value || !value->GetAsDictionary(&dictionary) || !dictionary) { 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Invalid response from service"; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::ListValue* printers = NULL; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (dictionary->GetList(kPrintersJsonValueName, &printers) && printers) { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < printers->GetSize(); ++i) { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string printer; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (printers->GetString(i, &printer) && !printer.empty()) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printers_.push_back(printer); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dictionary->GetBoolean(kXpsAvailableJsonValueName, &is_xps_available_); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dictionary->GetString(kUserNameJsonValueName, &user_name_); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 chrome_path; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dictionary->GetString(kChromePathJsonValueName, &chrome_path); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome_path_ = base::FilePath(chrome_path); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 user_data_dir; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dictionary->GetString(kUserDataDirJsonValueName, &user_data_dir); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_data_dir_ = base::FilePath(user_data_dir); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) succeded_ = true; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) done_event_->Signal(); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetupListener::OnChannelError() { 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) done_event_->Signal(); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SetupListener::WaitResponce(const base::TimeDelta& delta) { 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return done_event_->TimedWait(delta) && succeded_; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetupListener::Disconnect() { 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) channel_.reset(); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ipc_thread_->message_loop()->QuitWhenIdle(); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SetupListener::Connect(const base::string16& user) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ATL::CDacl dacl; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ATL::CSid user_sid; 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!user_sid.LoadAccount(ReplaceLocalHostInName(user).c_str())) { 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Unable to load Sid for" << user; 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dacl.AddAllowedAce(user_sid, GENERIC_READ | GENERIC_WRITE); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ATL::CSecurityDesc desk; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desk.SetDacl(dacl); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ATL::CSecurityAttributes attribs(desk); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedHandle pipe( 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateNamedPipe(kSetupPipeName, 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FILE_FLAG_FIRST_PIPE_INSTANCE, 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC::Channel::kReadBufferSize, 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC::Channel::kReadBufferSize, 5000, &attribs)); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pipe.IsValid()) { 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci channel_ = IPC::Channel::CreateServer(IPC::ChannelHandle(pipe.Get()), 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) channel_->Connect(); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 126