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