Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / panels / panel_host.cc
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/ui/panels/panel_host.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/chrome_page_zoom.h"
12 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
13 #include "chrome/browser/extensions/window_controller.h"
14 #include "chrome/browser/favicon/favicon_tab_helper.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/sessions/session_tab_helper.h"
17 #include "chrome/browser/ui/browser_navigator.h"
18 #include "chrome/browser/ui/panels/panel.h"
19 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
20 #include "content/public/browser/invalidate_type.h"
21 #include "content/public/browser/navigation_controller.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/notification_source.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/site_instance.h"
27 #include "content/public/browser/user_metrics.h"
28 #include "content/public/browser/web_contents.h"
29 #include "extensions/browser/view_type_utils.h"
30 #include "extensions/common/extension_messages.h"
31 #include "ipc/ipc_message.h"
32 #include "ipc/ipc_message_macros.h"
33 #include "ui/gfx/image/image.h"
34 #include "ui/gfx/rect.h"
35
36 using base::UserMetricsAction;
37
38 PanelHost::PanelHost(Panel* panel, Profile* profile)
39     : panel_(panel),
40       profile_(profile),
41       extension_function_dispatcher_(profile, this),
42       weak_factory_(this) {
43 }
44
45 PanelHost::~PanelHost() {
46 }
47
48 void PanelHost::Init(const GURL& url) {
49   if (url.is_empty())
50     return;
51
52   content::WebContents::CreateParams create_params(
53       profile_, content::SiteInstance::CreateForURL(profile_, url));
54   web_contents_.reset(content::WebContents::Create(create_params));
55   extensions::SetViewType(web_contents_.get(), extensions::VIEW_TYPE_PANEL);
56   web_contents_->SetDelegate(this);
57   content::WebContentsObserver::Observe(web_contents_.get());
58
59   // Needed to give the web contents a Tab ID. Extension APIs
60   // expect web contents to have a Tab ID.
61   SessionTabHelper::CreateForWebContents(web_contents_.get());
62   SessionTabHelper::FromWebContents(web_contents_.get())->SetWindowID(
63       panel_->session_id());
64
65   FaviconTabHelper::CreateForWebContents(web_contents_.get());
66   PrefsTabHelper::CreateForWebContents(web_contents_.get());
67   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
68       web_contents_.get());
69
70   web_contents_->GetController().LoadURL(
71       url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string());
72 }
73
74 void PanelHost::DestroyWebContents() {
75   // Cannot do a web_contents_.reset() because web_contents_.get() will
76   // still return the pointer when we CHECK in WebContentsDestroyed (or if
77   // we get called back in the middle of web contents destruction, which
78   // WebView might do when it detects the web contents is destroyed).
79   content::WebContents* contents = web_contents_.release();
80   delete contents;
81 }
82
83 gfx::Image PanelHost::GetPageIcon() const {
84   if (!web_contents_.get())
85     return gfx::Image();
86
87   FaviconTabHelper* favicon_tab_helper =
88       FaviconTabHelper::FromWebContents(web_contents_.get());
89   CHECK(favicon_tab_helper);
90   return favicon_tab_helper->GetFavicon();
91 }
92
93 content::WebContents* PanelHost::OpenURLFromTab(
94     content::WebContents* source,
95     const content::OpenURLParams& params) {
96   // These dispositions aren't really navigations.
97   if (params.disposition == SUPPRESS_OPEN ||
98       params.disposition == SAVE_TO_DISK ||
99       params.disposition == IGNORE_ACTION)
100     return NULL;
101
102   // Only allow clicks on links.
103   if (params.transition != content::PAGE_TRANSITION_LINK)
104     return NULL;
105
106   // Force all links to open in a new tab.
107   chrome::NavigateParams navigate_params(profile_,
108                                          params.url,
109                                          params.transition);
110   switch (params.disposition) {
111     case NEW_BACKGROUND_TAB:
112     case NEW_WINDOW:
113     case OFF_THE_RECORD:
114       navigate_params.disposition = params.disposition;
115       break;
116     default:
117       navigate_params.disposition = NEW_FOREGROUND_TAB;
118       break;
119   }
120   chrome::Navigate(&navigate_params);
121   return navigate_params.target_contents;
122 }
123
124 void PanelHost::NavigationStateChanged(const content::WebContents* source,
125                                        unsigned changed_flags) {
126   // Only need to update the title if the title changed while not loading,
127   // because the title is also updated when loading state changes.
128   if ((changed_flags & content::INVALIDATE_TYPE_TAB) ||
129       ((changed_flags & content::INVALIDATE_TYPE_TITLE) &&
130        !source->IsLoading()))
131     panel_->UpdateTitleBar();
132 }
133
134 void PanelHost::AddNewContents(content::WebContents* source,
135                                content::WebContents* new_contents,
136                                WindowOpenDisposition disposition,
137                                const gfx::Rect& initial_pos,
138                                bool user_gesture,
139                                bool* was_blocked) {
140   chrome::NavigateParams navigate_params(profile_, new_contents->GetURL(),
141                                          content::PAGE_TRANSITION_LINK);
142   navigate_params.target_contents = new_contents;
143
144   // Force all links to open in a new tab, even if they were trying to open a
145   // window.
146   navigate_params.disposition =
147       disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB;
148
149   navigate_params.window_bounds = initial_pos;
150   navigate_params.user_gesture = user_gesture;
151   navigate_params.extension_app_id = panel_->extension_id();
152   chrome::Navigate(&navigate_params);
153 }
154
155 void PanelHost::ActivateContents(content::WebContents* contents) {
156   panel_->Activate();
157 }
158
159 void PanelHost::DeactivateContents(content::WebContents* contents) {
160   panel_->Deactivate();
161 }
162
163 void PanelHost::LoadingStateChanged(content::WebContents* source,
164     bool to_different_document) {
165   bool is_loading = source->IsLoading() && to_different_document;
166   panel_->LoadingStateChanged(is_loading);
167 }
168
169 void PanelHost::CloseContents(content::WebContents* source) {
170   panel_->Close();
171 }
172
173 void PanelHost::MoveContents(content::WebContents* source,
174                              const gfx::Rect& pos) {
175   panel_->SetBounds(pos);
176 }
177
178 bool PanelHost::IsPopupOrPanel(const content::WebContents* source) const {
179   return true;
180 }
181
182 void PanelHost::ContentsZoomChange(bool zoom_in) {
183   Zoom(zoom_in ? content::PAGE_ZOOM_IN : content::PAGE_ZOOM_OUT);
184 }
185
186 void PanelHost::HandleKeyboardEvent(
187     content::WebContents* source,
188     const content::NativeWebKeyboardEvent& event) {
189   return panel_->HandleKeyboardEvent(event);
190 }
191
192 void PanelHost::WebContentsFocused(content::WebContents* contents) {
193   panel_->WebContentsFocused(contents);
194 }
195
196 void PanelHost::ResizeDueToAutoResize(content::WebContents* web_contents,
197                                       const gfx::Size& new_size) {
198   panel_->OnContentsAutoResized(new_size);
199 }
200
201 void PanelHost::RenderViewCreated(content::RenderViewHost* render_view_host) {
202   extensions::WindowController* window = GetExtensionWindowController();
203   render_view_host->Send(new ExtensionMsg_UpdateBrowserWindowId(
204       render_view_host->GetRoutingID(), window->GetWindowId()));
205 }
206
207 void PanelHost::RenderProcessGone(base::TerminationStatus status) {
208   CloseContents(web_contents_.get());
209 }
210
211 void PanelHost::WebContentsDestroyed(content::WebContents* web_contents) {
212   // Web contents should only be destroyed by us.
213   CHECK(!web_contents_.get());
214
215   // Close the panel after we return to the message loop (not immediately,
216   // otherwise, it may destroy this object before the stack has a chance
217   // to cleanly unwind.)
218   base::MessageLoop::current()->PostTask(
219       FROM_HERE,
220       base::Bind(&PanelHost::ClosePanel, weak_factory_.GetWeakPtr()));
221 }
222
223 void PanelHost::ClosePanel() {
224   panel_->Close();
225 }
226
227 bool PanelHost::OnMessageReceived(const IPC::Message& message) {
228   bool handled = true;
229   IPC_BEGIN_MESSAGE_MAP(PanelHost, message)
230     IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
231     IPC_MESSAGE_UNHANDLED(handled = false)
232   IPC_END_MESSAGE_MAP()
233   return handled;
234 }
235
236 void PanelHost::OnRequest(const ExtensionHostMsg_Request_Params& params) {
237   if (!web_contents_.get())
238     return;
239
240   extension_function_dispatcher_.Dispatch(params,
241                                           web_contents_->GetRenderViewHost());
242 }
243
244 extensions::WindowController* PanelHost::GetExtensionWindowController() const {
245   return panel_->extension_window_controller();
246 }
247
248 content::WebContents* PanelHost::GetAssociatedWebContents() const {
249   return web_contents_.get();
250 }
251
252 void PanelHost::Reload() {
253   content::RecordAction(UserMetricsAction("Reload"));
254   web_contents_->GetController().Reload(true);
255 }
256
257 void PanelHost::ReloadIgnoringCache() {
258   content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
259   web_contents_->GetController().ReloadIgnoringCache(true);
260 }
261
262 void PanelHost::StopLoading() {
263   content::RecordAction(UserMetricsAction("Stop"));
264   web_contents_->Stop();
265 }
266
267 void PanelHost::Zoom(content::PageZoom zoom) {
268   chrome_page_zoom::Zoom(web_contents_.get(), zoom);
269 }