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

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

Issue 174206: Bring up Firefox Password Import Unittest on OS X. (Closed)
Patch Set: Small fix Created 11 years, 4 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
OLDNEW
(Empty)
1 // Copyright (c) 2009 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/command_line.h"
8 #include "base/debug_on_start.h"
9 #include "base/file_path.h"
10 #include "base/message_loop.h"
11 #include "chrome/browser/importer/firefox_importer_utils.h"
12 #include "ipc/ipc_channel.h"
13 #include "ipc/ipc_descriptors.h"
14 #include "ipc/ipc_message.h"
15 #include "ipc/ipc_message_utils.h"
16 #include "ipc/ipc_switches.h"
17 #include "testing/multiprocess_func_list.h"
18
19 // Definition of IPC Messages used for this test.
20 #define MESSAGES_INTERNAL_FILE \
21 "chrome/browser/importer/firefox_importer_unittest_messages_internal.h"
22 #include "ipc/ipc_message_macros.h"
23
24 namespace {
25
26 // Name of IPC Channel to use for Server<-> Child Communications.
27 const char kTestChannelID[] = "T1";
28
29 // Launch the child process:
30 // |nss_path| - path to the NSS directory holding the decryption libraries.
31 // |channel| - IPC Channel to use for communication.
32 // |handle| - On return, the process handle to use to communicate with the
33 // child.
34 bool LaunchNSSDecrypterChildProcess(std::wstring& nss_path,
35 IPC::Channel& channel, base::ProcessHandle* handle) {
kuchhal 2009/08/21 16:24:57 make nss_path const and may be channel too.
36 CommandLine cl(*CommandLine::ForCurrentProcess());
37 cl.AppendSwitchWithValue(L"client", L"NSSDecrypterChildProcess");
38
39 FilePath ff_dylib_dir = FilePath::FromWStringHack(nss_path);
40 // Set env variable needed for FF encryption libs to load.
41 base::environment_vector env;
42 std::pair<const char*,const char*> dyld_override;
43 dyld_override.first = "DYLD_FALLBACK_LIBRARY_PATH";
John Grabowski 2009/08/21 01:13:18 Add comment explaining use of DYLD_FALLBACK_LIBRAR
44 dyld_override.second = ff_dylib_dir.value().c_str();
45 env.push_back(dyld_override);
46
47 base::file_handle_mapping_vector fds_to_map;
48 const int ipcfd = channel.GetClientFileDescriptor();
49 if (ipcfd > -1) {
50 fds_to_map.push_back(std::pair<int,int>(ipcfd, kPrimaryIPCChannel + 3));
51 } else {
52 return false;
53 }
54
55 bool debug_on_start = CommandLine::ForCurrentProcess()->HasSwitch(
56 switches::kDebugChildren);
57 return base::LaunchApp(cl.argv(), env, fds_to_map, debug_on_start,
58 handle);
59 }
60
61 } // namespace
62
63 //----------------------- Server --------------------
64
65 // Class to communicate on the server side of the IPC Channel.
66 // Method calls are sent over IPC and replies are read back into class
67 // variables.
68 // This class relies needs to be called on a single thread.
John Grabowski 2009/08/21 01:13:18 remove "relies"
69 class FFDecryptorServerChannelListener : public IPC::Channel::Listener {
70 public:
71 FFDecryptorServerChannelListener()
72 : got_result(false), sender_(NULL) {}
73
74 void SetSender(IPC::Message::Sender* sender) {
75 sender_ = sender;
76 }
77
78 void OnInitDecryptorResponse(bool result) {
79 DCHECK(!got_result);
80 result_bool = result;
81 got_result = true;
82 MessageLoop::current()->Quit();
83 }
84
85 void OnDecryptedTextResonse(std::wstring decrypted_text) {
86 DCHECK(!got_result);
87 result_string = decrypted_text;
88 got_result = true;
89 MessageLoop::current()->Quit();
90 }
91
92 void QuitClient() {
93 if (sender_)
94 sender_->Send(new Msg_Decryptor_Quit());
95 }
96
97 virtual void OnMessageReceived(const IPC::Message& msg) {
98 IPC_BEGIN_MESSAGE_MAP(FFDecryptorServerChannelListener, msg)
99 IPC_MESSAGE_HANDLER(Msg_Decryptor_InitReturnCode, OnInitDecryptorResponse)
100 IPC_MESSAGE_HANDLER(Msg_Decryptor_Response, OnDecryptedTextResonse)
101 IPC_END_MESSAGE_MAP()
102 }
103
104 // If an error occured, just kill the message Loop.
105 virtual void OnChannelError() {
106 got_result = false;
107 MessageLoop::current()->Quit();
108 }
109
110 // Results of IPC calls.
111 std::wstring result_string;
112 bool result_bool;
113 // True if IPC call succeeded and data in above variables is valid.
114 bool got_result;
115
116 private:
117 IPC::Message::Sender* sender_;
John Grabowski 2009/08/21 01:13:18 // weak
118 };
119
120 FFUnitTestDecryptorProxy::FFUnitTestDecryptorProxy(std::wstring &nss_path,
121 bool* success)
122 : child_process_(0) {
123 // Create a new message loop and spawn the child process.
124 message_loop_.reset(new MessageLoopForIO());
125
126 listener_.reset(new FFDecryptorServerChannelListener());
127 channel_.reset(new IPC::Channel(kTestChannelID,
128 IPC::Channel::MODE_SERVER,
129 listener_.get()));
130 channel_->Connect();
131 listener_->SetSender(channel_.get());
132
133 // Spawn child and set up sync IPC connection.
134 bool ret = LaunchNSSDecrypterChildProcess(nss_path,
135 *(channel_.get()),
136 &child_process_);
137 *success = ret && (child_process_ != 0);
138 }
139
140 FFUnitTestDecryptorProxy::~FFUnitTestDecryptorProxy() {
141 listener_->QuitClient();
142 channel_->Close();
143
144 if (child_process_) {
145 base::WaitForSingleProcess(child_process_, 5000);
146 base::CloseProcessHandle(child_process_);
147 }
148 }
149
150 // A message_loop task that quits the message loop when invoked, setting cancel
151 // causes the task to do nothing when invoked.
152 class CancellableQuitMsgLoop : public base::RefCounted<CancellableQuitMsgLoop> {
153 public:
154 CancellableQuitMsgLoop() : cancelled_(false) {}
155 void QuitNow() {
156 if (!cancelled_)
157 MessageLoop::current()->Quit();
158 }
159 bool cancelled_;
160 };
161
162 // Spin until either a client response arrives or a timeout occurs.
163 bool FFUnitTestDecryptorProxy::WaitForClientResponse() {
164 const int64 kLoopTimeoutMS = 3 * 1000; // 3 seconds.
John Grabowski 2009/08/21 01:13:18 Jack up to help prevent flaky tests
165
166 // What we're trying to do here is to wait for an RPC message to go over the
167 // wire and the client to reply. If the client does relpy by a given timeout
kuchhal 2009/08/21 16:24:57 does *not reply*
168 // we kill the message loop.
169 // The way we do this is to post a CancellableQuitMsgLoop for 3 seconds in
170 // the future and cancel it if an RPC message comes back earlier.
171 // This relies on the IPC listener class to quit the message loop itself when
172 // a message comes in.
173 scoped_refptr<CancellableQuitMsgLoop> quit_task =
174 new CancellableQuitMsgLoop();
175 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(
176 quit_task.get(), &CancellableQuitMsgLoop::QuitNow), kLoopTimeoutMS);
177
178 message_loop_->Run();
179 bool ret = !quit_task->cancelled_;
180 quit_task->cancelled_ = false;
181 return ret;
182 }
183
184 bool FFUnitTestDecryptorProxy::Init(const std::wstring& dll_path,
185 const std::wstring& db_path) {
186 channel_->Send(new Msg_Decryptor_Init(dll_path, db_path));
187 bool ok = WaitForClientResponse();
188 if (ok && listener_->got_result) {
189 listener_->got_result = false;
190 return listener_->result_bool;
191 }
192 return false;
193 }
194
195 std::wstring FFUnitTestDecryptorProxy::Decrypt(const std::string& crypt) {
196 channel_->Send(new Msg_Decrypt(crypt));
197 bool ok = WaitForClientResponse();
198 if (ok && listener_->got_result) {
199 listener_->got_result = false;
200 return listener_->result_string;
201 }
202 return L"";
203 }
204
205 //---------------------------- Child Process -----------------------
206
207 // Class to listen on the client side of the ipc channel, it calls through
208 // to the NSSDecryptor and sends back a reply.
209 class FFDecryptorClientChannelListener : public IPC::Channel::Listener {
210 public:
211 FFDecryptorClientChannelListener()
212 : sender_(NULL) {}
213
214 void SetSender(IPC::Message::Sender* sender) {
215 sender_ = sender;
216 }
217
218 void OnDecryptor_Init(std::wstring dll_path, std::wstring db_path) {
219 bool ret = decryptor_.Init(dll_path, db_path);
220 sender_->Send(new Msg_Decryptor_InitReturnCode(ret));
221 }
222
223 void OnDecrypt(std::string crypt) {
224 std::wstring unencrypted_str = decryptor_.Decrypt(crypt);
225 sender_->Send(new Msg_Decryptor_Response(unencrypted_str));
226 }
227
228 void OnQuitRequest() {
229 MessageLoop::current()->Quit();
230 }
231
232 virtual void OnMessageReceived(const IPC::Message& msg) {
233 IPC_BEGIN_MESSAGE_MAP(FFDecryptorClientChannelListener, msg)
234 IPC_MESSAGE_HANDLER(Msg_Decryptor_Init, OnDecryptor_Init)
235 IPC_MESSAGE_HANDLER(Msg_Decrypt, OnDecrypt)
236 IPC_MESSAGE_HANDLER(Msg_Decryptor_Quit, OnQuitRequest)
237 IPC_END_MESSAGE_MAP()
238 }
239
240 virtual void OnChannelError() {
241 MessageLoop::current()->Quit();
242 }
243
244 private:
245 NSSDecryptor decryptor_;
246 IPC::Message::Sender* sender_;
247 };
248
249 // Entry function in child process.
250 MULTIPROCESS_TEST_MAIN(NSSDecrypterChildProcess) {
251 MessageLoopForIO main_message_loop;
252 FFDecryptorClientChannelListener listener;
253
254 IPC::Channel channel(kTestChannelID, IPC::Channel::MODE_CLIENT, &listener);
255 channel.Connect();
256 listener.SetSender(&channel);
257
258 // run message loop
259 MessageLoop::current()->Run();
260
261 return 0;
262 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698