1 // Copyright (c) 2011 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.
6 #include "base/bind_helpers.h"
7 #include "base/lazy_instance.h"
8 #include "base/location.h"
9 #include "chrome_frame/external_tab.h"
10 #include "base/task.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "chrome/common/automation_messages.h"
13 #include "chrome_frame/chrome_frame_delegate.h"
14 #include "chrome_frame/utils.h"
17 static base::LazyInstance
<ChromeProxyFactory
> g_proxy_factory
=
18 LAZY_INSTANCE_INITIALIZER
;
20 struct UserDataHolder
: public SyncMessageContext
{
21 explicit UserDataHolder(void* p
) : data(p
) {}
27 ExternalTabProxy::ExternalTabProxy() : state_(NONE
), tab_(0), tab_wnd_(NULL
),
28 chrome_wnd_(NULL
), proxy_factory_(g_proxy_factory
.Pointer()), proxy_(NULL
),
32 ExternalTabProxy::~ExternalTabProxy() {
36 bool ExternalTabProxy::OnMessageReceived(const IPC::Message
& message
) {
38 IPC_BEGIN_MESSAGE_MAP(ExternalTabProxy
, message
)
39 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationStateChanged
,
40 OnNavigationStateChanged
)
41 IPC_MESSAGE_HANDLER(AutomationMsg_UpdateTargetUrl
, OnUpdateTargetUrl
)
42 IPC_MESSAGE_HANDLER(AutomationMsg_HandleAccelerator
, OnHandleAccelerator
)
43 IPC_MESSAGE_HANDLER(AutomationMsg_TabbedOut
, OnTabbedOut
)
44 IPC_MESSAGE_HANDLER(AutomationMsg_OpenURL
, OnOpenURL
)
45 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationFailed
, OnNavigationFailed
)
46 IPC_MESSAGE_HANDLER(AutomationMsg_DidNavigate
, OnDidNavigate
)
47 IPC_MESSAGE_HANDLER(AutomationMsg_TabLoaded
, OnTabLoaded
)
48 IPC_MESSAGE_HANDLER(AutomationMsg_MoveWindow
, OnMoveWindow
)
49 IPC_MESSAGE_HANDLER(AutomationMsg_ForwardMessageToExternalHost
,
51 IPC_MESSAGE_HANDLER(AutomationMsg_ForwardContextMenuToExternalHost
,
53 IPC_MESSAGE_HANDLER(AutomationMsg_RequestStart
, OnNetwork_Start
)
54 IPC_MESSAGE_HANDLER(AutomationMsg_RequestRead
, OnNetwork_Read
)
55 IPC_MESSAGE_HANDLER(AutomationMsg_RequestEnd
, OnNetwork_End
)
56 IPC_MESSAGE_HANDLER(AutomationMsg_DownloadRequestInHost
,
57 OnNetwork_DownloadInHost
)
58 IPC_MESSAGE_HANDLER(AutomationMsg_GetCookiesFromHost
, OnGetCookies
)
59 IPC_MESSAGE_HANDLER(AutomationMsg_SetCookieAsync
, OnSetCookie
)
60 IPC_MESSAGE_HANDLER(AutomationMsg_AttachExternalTab
, OnAttachTab
)
61 IPC_MESSAGE_HANDLER(AutomationMsg_RequestGoToHistoryEntryOffset
,
63 IPC_MESSAGE_HANDLER(AutomationMsg_CloseExternalTab
, OnTabClosed
)
64 IPC_MESSAGE_UNHANDLED(handled
= false)
69 void ExternalTabProxy::Init() {
71 // Create a window on the UI thread for marshaling messages back and forth
72 // from the IPC thread. This window cannot be a message only window as the
73 // external chrome tab window initially is created as a child of this window
74 CWindowImpl
<ExternalTabProxy
>::Create(GetDesktopWindow(), NULL
, NULL
,
75 WS_CHILDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, WS_EX_TOOLWINDOW
);
76 DCHECK(m_hWnd
!= NULL
);
77 ui_
.SetWindow(m_hWnd
, WM_APP
+ 6);
81 void ExternalTabProxy::Destroy() {
82 DCHECK(NULL
== done_
.get());
83 // TODO(stoyan): Should we release proxy first and then destroy the window
84 // (parent of the chrome window) or the other way around?
86 done_
.reset(new base::WaitableEvent(true, false));
87 proxy_factory_
->ReleaseProxy(this, tab_params_
.proxy_params
.profile
);
94 CWindowImpl
<ExternalTabProxy
>::DestroyWindow();
97 // We shall tell the TaskMarshaller to delete queued tasks.
102 void ExternalTabProxy::CreateTab(const CreateTabParams
& create_params
,
103 UIDelegate
* delegate
) {
104 DCHECK(ui_delegate_
== NULL
);
105 DCHECK_EQ(NONE
, state_
);
106 // Create host window if needed.
108 ui_delegate_
= delegate
;
109 // TODO(stoyan): Shall we check the CanNavigate(create_params.url)?
110 tab_params_
= create_params
;
111 state_
= INIT_IN_PROGRESS
;
112 proxy_factory_
->GetProxy(this, create_params
.proxy_params
);
115 void ExternalTabProxy::Connected(ChromeProxy
* proxy
) {
117 ui_
.PostTask(FROM_HERE
, base::Bind(&ExternalTabProxy::UiConnected
,
118 base::Unretained(this), proxy
));
121 void ExternalTabProxy::UiConnected(ChromeProxy
* proxy
) {
123 ExternalTabSettings settings
;
124 settings
.parent
= m_hWnd
;
125 settings
.style
= WS_CHILD
;
126 settings
.is_incognito
= tab_params_
.is_incognito
;
127 // TODO(stoyan): FIX this.
128 settings
.load_requests_via_automation
= true;
129 // TODO(stoyan): FIX this.
130 settings
.handle_top_level_requests
= true;
131 settings
.initial_url
= tab_params_
.url
;
132 settings
.referrer
= tab_params_
.referrer
;
133 // Infobars are disabled in widget mode.
134 settings
.infobars_enabled
= !tab_params_
.is_widget_mode
;
135 // TODO(stoyan): FIX this.
136 settings
.route_all_top_level_navigations
= false;
138 state_
= CREATE_TAB_IN_PROGRESS
;
139 proxy
->CreateTab(this, settings
);
142 void ExternalTabProxy::Disconnected() {
144 DCHECK(done_
.get() != NULL
);
148 void ExternalTabProxy::PeerLost(ChromeProxy
* proxy
, DisconnectReason reason
) {
149 ui_
.PostTask(FROM_HERE
, base::Bind(&ExternalTabProxy::UiPeerLost
,
150 base::Unretained(this), proxy
, reason
));
153 void ExternalTabProxy::UiPeerLost(ChromeProxy
* proxy
, DisconnectReason reason
) {
157 void ExternalTabProxy::Navigate(const std::string
& url
,
158 const std::string
& referrer
,
159 NavigationConstraints
* navigation_constraints
) {
161 // Catch invalid URLs early. Can we allow this navigation to happen?
162 GURL
parsed_url(url
);
163 if (!CanNavigate(parsed_url
, navigation_constraints
)) {
164 DLOG(ERROR
) << __FUNCTION__
<< " Not allowing navigation to: " << url
;
168 GURL
parsed_referrer(referrer
);
169 // If we are still establishing channel, simply replace the params
170 if (state_
== INIT_IN_PROGRESS
) {
171 tab_params_
.url
= parsed_url
;
172 tab_params_
.referrer
= parsed_referrer
;
175 // Ah! Too late. Wait to get tab handle and then navigate.
176 if (state_
== CREATE_TAB_IN_PROGRESS
) {
177 pending_navigation_
.Set(parsed_url
, parsed_referrer
);
180 if (state_
== READY
) {
181 proxy_
->Tab_Navigate(tab_
, parsed_url
, parsed_referrer
);
185 void ExternalTabProxy::ConnectToExternalTab(uint64 external_tab_cookie
) {
186 proxy_
->ConnectTab(this, m_hWnd
, external_tab_cookie
);
189 void ExternalTabProxy::BlockExternalTab(uint64 cookie
) {
190 proxy_
->BlockTab(cookie
);
193 void ExternalTabProxy::SetZoomLevel(content::PageZoom zoom_level
) {
194 proxy_
->Tab_Zoom(tab_
, zoom_level
);
197 void ExternalTabProxy::NavigateToIndex(int index
) {
201 void ExternalTabProxy::ForwardMessageFromExternalHost(
202 const std::string
& message
, const std::string
& origin
,
203 const std::string
& target
) {
204 proxy_
->Tab_PostMessage(tab_
, message
, origin
, target
);
207 void ExternalTabProxy::ChromeFrameHostMoved() {
208 proxy_
->Tab_OnHostMoved(tab_
);
211 //////////////////////////////////////////////////////////////////////////
212 void ExternalTabProxy::UiCompleted_CreateTab(bool success
, HWND chrome_window
,
213 HWND tab_window
, int tab_handle
,
218 tab_wnd_
= tab_window
;
219 chrome_wnd_
= chrome_window
;
221 // If a navigation request came while tab creation was in progress -
222 // go ahead and navigate.
223 if (pending_navigation_
.url
.is_valid())
224 proxy_
->Tab_Navigate(tab_
, pending_navigation_
.url
,
225 pending_navigation_
.referrer
);
229 void ExternalTabProxy::Completed_CreateTab(bool success
, HWND chrome_wnd
,
230 HWND tab_window
, int tab_handle
,
234 FROM_HERE
, base::Bind(&ExternalTabProxy::UiCompleted_CreateTab
,
235 base::Unretained(this), success
, chrome_wnd
,
236 tab_window
, tab_handle
, session_id
));
239 void ExternalTabProxy::Completed_ConnectToTab(
240 bool success
, HWND chrome_window
, HWND tab_window
, int tab_handle
,
245 void ExternalTabProxy::Completed_Navigate(
246 bool success
, enum AutomationMsg_NavigationResponseValues res
) {
251 void ExternalTabProxy::OnNavigationStateChanged(
252 int flags
, const NavigationInfo
& nav_info
) {
253 ui_
.PostTask(FROM_HERE
,
254 base::Bind(&UIDelegate::OnNavigationStateChanged
,
255 base::Unretained(ui_delegate_
), flags
, nav_info
));
258 void ExternalTabProxy::OnUpdateTargetUrl(const std::wstring
& url
) {
259 ui_
.PostTask(FROM_HERE
, base::Bind(&UIDelegate::OnUpdateTargetUrl
,
260 base::Unretained(ui_delegate_
), url
));
263 void ExternalTabProxy::OnTabLoaded(const GURL
& url
) {
264 ui_
.PostTask(FROM_HERE
, base::Bind(&UIDelegate::OnLoad
,
265 base::Unretained(ui_delegate_
), url
));
268 void ExternalTabProxy::OnMoveWindow(const gfx::Rect
& pos
) {
269 ui_
.PostTask(FROM_HERE
, base::Bind(&UIDelegate::OnMoveWindow
,
270 base::Unretained(ui_delegate_
), pos
));
273 void ExternalTabProxy::OnMessageToHost(const std::string
& message
,
274 const std::string
& origin
,
275 const std::string
& target
) {
278 base::Bind(&UIDelegate::OnMessageFromChromeFrame
,
279 base::Unretained(ui_delegate_
), message
, origin
, target
));
282 void ExternalTabProxy::OnHandleAccelerator(const MSG
& accel_message
) {
283 ui_
.PostTask(FROM_HERE
,
284 base::Bind(&UIDelegate::OnHandleAccelerator
,
285 base::Unretained(ui_delegate_
), accel_message
));
288 void ExternalTabProxy::OnHandleContextMenu(
289 const ContextMenuModel
& context_menu_model
,
291 const MiniContextMenuParams
& params
) {
292 ui_
.PostTask(FROM_HERE
,
293 base::Bind(&UIDelegate::OnHandleContextMenu
,
294 base::Unretained(ui_delegate_
), context_menu_model
,
295 align_flags
, params
));
298 void ExternalTabProxy::OnTabbedOut(bool reverse
) {
299 ui_
.PostTask(FROM_HERE
, base::Bind(&UIDelegate::OnTabbedOut
,
300 base::Unretained(ui_delegate_
), reverse
));
303 void ExternalTabProxy::OnGoToHistoryOffset(int offset
) {
304 ui_
.PostTask(FROM_HERE
, base::Bind(&UIDelegate::OnGoToHistoryOffset
,
305 base::Unretained(ui_delegate_
), offset
));
308 void ExternalTabProxy::OnOpenURL(const GURL
& url_to_open
, const GURL
& referrer
,
309 int open_disposition
) {
312 base::Bind(&UIDelegate::OnOpenURL
, base::Unretained(ui_delegate_
),
313 url_to_open
, referrer
, open_disposition
));
316 void ExternalTabProxy::OnNavigationFailed(int error_code
, const GURL
& gurl
) {
320 void ExternalTabProxy::OnDidNavigate(const NavigationInfo
& navigation_info
) {
324 void ExternalTabProxy::OnNetwork_Start(
325 int request_id
, const AutomationURLRequest
& request_info
) {
326 // TODO(stoyan): url_fetcher_.Start();
329 void ExternalTabProxy::OnNetwork_Read(int request_id
, int bytes_to_read
) {
330 // TODO(stoyan): url_fetcher_.Read();
333 void ExternalTabProxy::OnNetwork_End(int request_id
,
334 const net::URLRequestStatus
& s
) {
338 void ExternalTabProxy::OnNetwork_DownloadInHost(int request_id
) {
342 void ExternalTabProxy::OnGetCookies(const GURL
& url
, int cookie_id
) {
346 void ExternalTabProxy::OnSetCookie(const GURL
& url
, const std::string
& cookie
) {
350 void ExternalTabProxy::OnTabClosed() {
354 void ExternalTabProxy::OnAttachTab(
355 const AttachExternalTabParams
& attach_params
) {