OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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_frame/test/net/process_singleton_subclass.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/path_service.h" | |
9 #include "base/string_util.h" | |
10 #include "chrome/browser/browser_process_impl.h" | |
11 #include "chrome/browser/profiles/profile_manager.h" | |
12 #include "chrome/common/chrome_constants.h" | |
13 #include "chrome/common/chrome_paths.h" | |
14 #include "chrome/common/chrome_switches.h" | |
15 #include "chrome_frame/test/net/test_automation_provider.h" | |
16 #include "chrome_frame/function_stub.h" | |
17 #include "testing/gtest/include/gtest/gtest.h" | |
18 | |
19 ProcessSingletonSubclass::ProcessSingletonSubclass( | |
20 ProcessSingletonSubclassDelegate* delegate) | |
21 : stub_(NULL), delegate_(delegate), original_wndproc_(NULL) { | |
22 } | |
23 | |
24 ProcessSingletonSubclass::~ProcessSingletonSubclass() { | |
25 if (stub_) { | |
26 stub_->BypassStub(reinterpret_cast<void*>(original_wndproc_)); | |
27 } | |
28 } | |
29 | |
30 bool ProcessSingletonSubclass::Subclass(const FilePath& user_data_dir) { | |
31 DCHECK(stub_ == NULL); | |
32 DCHECK(original_wndproc_ == NULL); | |
33 HWND hwnd = FindWindowEx(HWND_MESSAGE, NULL, chrome::kMessageWindowClass, | |
34 user_data_dir.value().c_str()); | |
35 if (!::IsWindow(hwnd)) | |
36 return false; | |
37 | |
38 // The window must be in this process for us to be able to subclass it. | |
39 DWORD pid = 0; | |
40 ::GetWindowThreadProcessId(hwnd, &pid); | |
41 EXPECT_EQ(pid, ::GetCurrentProcessId()); | |
42 | |
43 original_wndproc_ = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hwnd, | |
44 GWLP_WNDPROC)); | |
45 stub_ = FunctionStub::Create(reinterpret_cast<uintptr_t>(this), | |
46 &SubclassWndProc); | |
47 DCHECK(stub_); | |
48 ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, | |
49 reinterpret_cast<LONG_PTR>(stub_->code())); | |
50 return true; | |
51 } | |
52 | |
53 // static | |
54 LRESULT ProcessSingletonSubclass::SubclassWndProc(ProcessSingletonSubclass* me, | |
55 HWND hwnd, UINT msg, | |
56 WPARAM wp, LPARAM lp) { | |
57 switch (msg) { | |
58 case WM_COPYDATA: | |
59 return me->OnCopyData(hwnd, reinterpret_cast<HWND>(wp), | |
60 reinterpret_cast<COPYDATASTRUCT*>(lp)); | |
61 default: | |
62 break; | |
63 } | |
64 | |
65 return me->original_wndproc_(hwnd, msg, wp, lp); | |
66 } | |
67 | |
68 // static | |
69 LRESULT ProcessSingletonSubclass::OnCopyData(HWND hwnd, HWND from_hwnd, | |
70 const COPYDATASTRUCT* cds) { | |
71 // We should have enough room for the shortest command (min_message_size) | |
72 // and also be a multiple of wchar_t bytes. The shortest command | |
73 // possible is L"START\0\0" (empty current directory and command line). | |
74 static const int kMinMessageSize = sizeof(L"START\0"); | |
75 EXPECT_TRUE(kMinMessageSize <= cds->cbData); | |
76 | |
77 if (kMinMessageSize > cds->cbData) | |
78 return TRUE; | |
79 | |
80 // We split the string into 4 parts on NULLs. | |
81 const wchar_t* begin = reinterpret_cast<const wchar_t*>(cds->lpData); | |
82 const wchar_t* end = begin + (cds->cbData / sizeof(wchar_t)); | |
83 const wchar_t kNull = L'\0'; | |
84 const wchar_t* eos = wmemchr(begin, kNull, end - begin); | |
85 EXPECT_NE(eos, end); | |
86 if (lstrcmpW(begin, L"START") == 0) { | |
87 begin = eos + 1; | |
88 EXPECT_TRUE(begin <= end); | |
89 eos = wmemchr(begin, kNull, end - begin); | |
90 EXPECT_NE(eos, end); | |
91 | |
92 // Get current directory. | |
93 const wchar_t* cur_dir = begin; | |
94 begin = eos + 1; | |
95 EXPECT_TRUE(begin <= end); | |
96 eos = wmemchr(begin, kNull, end - begin); | |
97 // eos might be equal to end at this point. | |
98 | |
99 // Get command line. | |
100 std::wstring cmd_line(begin, static_cast<size_t>(end - begin)); | |
101 | |
102 CommandLine parsed_command_line = CommandLine::FromString(cmd_line); | |
103 std::string channel_id = parsed_command_line.GetSwitchValueASCII( | |
104 switches::kAutomationClientChannelID); | |
105 EXPECT_FALSE(channel_id.empty()); | |
106 | |
107 delegate_->OnConnectAutomationProviderToChannel(channel_id); | |
108 } | |
109 return TRUE; | |
110 } | |
OLD | NEW |