Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: chrome/browser/importer/firefox_importer_unittest_utils_mac.cc

Issue 18501013: Move most importer code to chrome/utility/importer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: another gyp attempt Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/importer/firefox_importer_unittest_utils.h"
6
7 #include "base/base_switches.h"
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.h"
12 #include "base/message_loop.h"
13 #include "base/test/test_timeouts.h"
14 #include "chrome/browser/importer/firefox_importer_utils.h"
15 #include "ipc/ipc_channel.h"
16 #include "ipc/ipc_descriptors.h"
17 #include "ipc/ipc_listener.h"
18 #include "ipc/ipc_message.h"
19 #include "ipc/ipc_multiprocess_test.h"
20 #include "ipc/ipc_switches.h"
21 #include "testing/multiprocess_func_list.h"
22
23 #define IPC_MESSAGE_IMPL
24 #include "chrome/browser/importer/firefox_importer_unittest_messages_internal.h"
25
26 namespace {
27
28 // Name of IPC Channel to use for Server<-> Child Communications.
29 const char kTestChannelID[] = "T1";
30
31 // Launch the child process:
32 // |nss_path| - path to the NSS directory holding the decryption libraries.
33 // |channel| - IPC Channel to use for communication.
34 // |handle| - On return, the process handle to use to communicate with the
35 // child.
36 bool LaunchNSSDecrypterChildProcess(const base::FilePath& nss_path,
37 IPC::Channel* channel, base::ProcessHandle* handle) {
38 CommandLine cl(*CommandLine::ForCurrentProcess());
39 cl.AppendSwitchASCII(switches::kTestChildProcess, "NSSDecrypterChildProcess");
40
41 // Set env variable needed for FF encryption libs to load.
42 // See "chrome/browser/importer/nss_decryptor_mac.mm" for an explanation of
43 // why we need this.
44 base::EnvironmentVector env;
45 std::pair<std::string, std::string> dyld_override;
46 dyld_override.first = "DYLD_FALLBACK_LIBRARY_PATH";
47 dyld_override.second = nss_path.value();
48 env.push_back(dyld_override);
49
50 int ipcfd = channel->TakeClientFileDescriptor();
51 if (ipcfd == -1)
52 return false;
53
54 file_util::ScopedFD client_file_descriptor_closer(&ipcfd);
55 base::FileHandleMappingVector fds_to_map;
56 fds_to_map.push_back(std::pair<int,int>(ipcfd, kPrimaryIPCChannel + 3));
57
58 bool debug_on_start = CommandLine::ForCurrentProcess()->HasSwitch(
59 switches::kDebugChildren);
60 base::LaunchOptions options;
61 options.environ = &env;
62 options.fds_to_remap = &fds_to_map;
63 options.wait = debug_on_start;
64 return base::LaunchProcess(cl.argv(), options, handle);
65 }
66
67 } // namespace
68
69 //----------------------- Server --------------------
70
71 // Class to communicate on the server side of the IPC Channel.
72 // Method calls are sent over IPC and replies are read back into class
73 // variables.
74 // This class needs to be called on a single thread.
75 class FFDecryptorServerChannelListener : public IPC::Listener {
76 public:
77 FFDecryptorServerChannelListener()
78 : got_result(false), sender_(NULL) {}
79
80 void SetSender(IPC::Sender* sender) {
81 sender_ = sender;
82 }
83
84 void OnInitDecryptorResponse(bool result) {
85 DCHECK(!got_result);
86 result_bool = result;
87 got_result = true;
88 base::MessageLoop::current()->Quit();
89 }
90
91 void OnDecryptedTextResonse(const string16& decrypted_text) {
92 DCHECK(!got_result);
93 result_string = decrypted_text;
94 got_result = true;
95 base::MessageLoop::current()->Quit();
96 }
97
98 void QuitClient() {
99 if (sender_)
100 sender_->Send(new Msg_Decryptor_Quit());
101 }
102
103 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
104 bool handled = true;
105 IPC_BEGIN_MESSAGE_MAP(FFDecryptorServerChannelListener, msg)
106 IPC_MESSAGE_HANDLER(Msg_Decryptor_InitReturnCode, OnInitDecryptorResponse)
107 IPC_MESSAGE_HANDLER(Msg_Decryptor_Response, OnDecryptedTextResonse)
108 IPC_MESSAGE_UNHANDLED(handled = false)
109 IPC_END_MESSAGE_MAP()
110 return handled;
111 }
112
113 // If an error occured, just kill the message Loop.
114 virtual void OnChannelError() OVERRIDE {
115 got_result = false;
116 base::MessageLoop::current()->Quit();
117 }
118
119 // Results of IPC calls.
120 string16 result_string;
121 bool result_bool;
122 // True if IPC call succeeded and data in above variables is valid.
123 bool got_result;
124
125 private:
126 IPC::Sender* sender_; // weak
127 };
128
129 FFUnitTestDecryptorProxy::FFUnitTestDecryptorProxy()
130 : child_process_(0) {
131 }
132
133 bool FFUnitTestDecryptorProxy::Setup(const base::FilePath& nss_path) {
134 // Create a new message loop and spawn the child process.
135 message_loop_.reset(new base::MessageLoopForIO());
136
137 listener_.reset(new FFDecryptorServerChannelListener());
138 channel_.reset(new IPC::Channel(kTestChannelID,
139 IPC::Channel::MODE_SERVER,
140 listener_.get()));
141 CHECK(channel_->Connect());
142 listener_->SetSender(channel_.get());
143
144 // Spawn child and set up sync IPC connection.
145 bool ret = LaunchNSSDecrypterChildProcess(nss_path,
146 channel_.get(),
147 &child_process_);
148 return ret && (child_process_ != 0);
149 }
150
151 FFUnitTestDecryptorProxy::~FFUnitTestDecryptorProxy() {
152 listener_->QuitClient();
153 channel_->Close();
154
155 if (child_process_) {
156 base::WaitForSingleProcess(child_process_, base::TimeDelta::FromSeconds(5));
157 base::CloseProcessHandle(child_process_);
158 }
159 }
160
161 // A message_loop task that quits the message loop when invoked, setting cancel
162 // causes the task to do nothing when invoked.
163 class CancellableQuitMsgLoop : public base::RefCounted<CancellableQuitMsgLoop> {
164 public:
165 CancellableQuitMsgLoop() : cancelled_(false) {}
166 void QuitNow() {
167 if (!cancelled_)
168 base::MessageLoop::current()->Quit();
169 }
170 bool cancelled_;
171
172 private:
173 friend class base::RefCounted<CancellableQuitMsgLoop>;
174 ~CancellableQuitMsgLoop() {}
175 };
176
177 // Spin until either a client response arrives or a timeout occurs.
178 bool FFUnitTestDecryptorProxy::WaitForClientResponse() {
179 // What we're trying to do here is to wait for an RPC message to go over the
180 // wire and the client to reply. If the client does not reply by a given
181 // timeout we kill the message loop.
182 // The way we do this is to post a CancellableQuitMsgLoop for 3 seconds in
183 // the future and cancel it if an RPC message comes back earlier.
184 // This relies on the IPC listener class to quit the message loop itself when
185 // a message comes in.
186 scoped_refptr<CancellableQuitMsgLoop> quit_task(
187 new CancellableQuitMsgLoop());
188 base::MessageLoop::current()->PostDelayedTask(
189 FROM_HERE,
190 base::Bind(&CancellableQuitMsgLoop::QuitNow, quit_task.get()),
191 TestTimeouts::action_max_timeout());
192
193 message_loop_->Run();
194 bool ret = !quit_task->cancelled_;
195 quit_task->cancelled_ = false;
196 return ret;
197 }
198
199 bool FFUnitTestDecryptorProxy::DecryptorInit(const base::FilePath& dll_path,
200 const base::FilePath& db_path) {
201 channel_->Send(new Msg_Decryptor_Init(dll_path, db_path));
202 bool ok = WaitForClientResponse();
203 if (ok && listener_->got_result) {
204 listener_->got_result = false;
205 return listener_->result_bool;
206 }
207 return false;
208 }
209
210 string16 FFUnitTestDecryptorProxy::Decrypt(const std::string& crypt) {
211 channel_->Send(new Msg_Decrypt(crypt));
212 bool ok = WaitForClientResponse();
213 if (ok && listener_->got_result) {
214 listener_->got_result = false;
215 return listener_->result_string;
216 }
217 return string16();
218 }
219
220 //---------------------------- Child Process -----------------------
221
222 // Class to listen on the client side of the ipc channel, it calls through
223 // to the NSSDecryptor and sends back a reply.
224 class FFDecryptorClientChannelListener : public IPC::Listener {
225 public:
226 FFDecryptorClientChannelListener()
227 : sender_(NULL) {}
228
229 void SetSender(IPC::Sender* sender) {
230 sender_ = sender;
231 }
232
233 void OnDecryptor_Init(base::FilePath dll_path, base::FilePath db_path) {
234 bool ret = decryptor_.Init(dll_path, db_path);
235 sender_->Send(new Msg_Decryptor_InitReturnCode(ret));
236 }
237
238 void OnDecrypt(std::string crypt) {
239 string16 unencrypted_str = decryptor_.Decrypt(crypt);
240 sender_->Send(new Msg_Decryptor_Response(unencrypted_str));
241 }
242
243 void OnQuitRequest() {
244 base::MessageLoop::current()->Quit();
245 }
246
247 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
248 bool handled = true;
249 IPC_BEGIN_MESSAGE_MAP(FFDecryptorClientChannelListener, msg)
250 IPC_MESSAGE_HANDLER(Msg_Decryptor_Init, OnDecryptor_Init)
251 IPC_MESSAGE_HANDLER(Msg_Decrypt, OnDecrypt)
252 IPC_MESSAGE_HANDLER(Msg_Decryptor_Quit, OnQuitRequest)
253 IPC_MESSAGE_UNHANDLED(handled = false)
254 IPC_END_MESSAGE_MAP()
255 return handled;
256 }
257
258 virtual void OnChannelError() OVERRIDE {
259 base::MessageLoop::current()->Quit();
260 }
261
262 private:
263 NSSDecryptor decryptor_;
264 IPC::Sender* sender_;
265 };
266
267 // Entry function in child process.
268 MULTIPROCESS_IPC_TEST_MAIN(NSSDecrypterChildProcess) {
269 base::MessageLoopForIO main_message_loop;
270 FFDecryptorClientChannelListener listener;
271
272 IPC::Channel channel(kTestChannelID, IPC::Channel::MODE_CLIENT, &listener);
273 CHECK(channel.Connect());
274 listener.SetSender(&channel);
275
276 // run message loop
277 base::MessageLoop::current()->Run();
278
279 return 0;
280 }
OLDNEW
« no previous file with comments | « chrome/browser/importer/firefox_importer_unittest_utils.h ('k') | chrome/browser/importer/firefox_importer_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698