blob: 56db088f813986ca8fb047ae4736f5b86858b3a1 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit09911bf2008-07-26 23:55:294
[email protected]3e45ba92009-02-20 21:09:005#if defined(OS_WIN)
[email protected]f3ec7742009-01-15 00:59:166#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]3e45ba92009-02-20 21:09:007#elif defined(OS_POSIX)
8#include "chrome/common/temp_scaffolding_stubs.h"
9#endif
initial.commit09911bf2008-07-26 23:55:2910
11#include "chrome/browser/cert_store.h"
[email protected]bcef0dc02009-02-28 00:35:0212#include "chrome/browser/download/download_item_model.h"
13#include "chrome/browser/download/download_shelf.h"
[email protected]f3ec7742009-01-15 00:59:1614#include "chrome/browser/tab_contents/navigation_entry.h"
15#include "chrome/browser/tab_contents/tab_contents_delegate.h"
16#include "chrome/browser/tab_contents/web_contents.h"
[email protected]a4feef82008-10-02 15:11:2217#include "chrome/common/l10n_util.h"
[email protected]bfd04a62009-02-01 18:16:5618#include "chrome/common/notification_service.h"
initial.commit09911bf2008-07-26 23:55:2919#include "chrome/common/pref_names.h"
[email protected]1eb89e82008-08-15 12:27:0320#include "chrome/common/pref_service.h"
[email protected]34ac8f32009-02-22 23:03:2721#include "grit/generated_resources.h"
[email protected]3e45ba92009-02-20 21:09:0022
23#if defined(OS_WIN)
24// TODO(port): some of these headers should be ported.
25#include "chrome/browser/tab_contents/infobar_delegate.h"
[email protected]3e45ba92009-02-20 21:09:0026#include "chrome/browser/views/download_started_animation.h"
27#include "chrome/browser/views/blocked_popup_container.h"
initial.commit09911bf2008-07-26 23:55:2928#include "chrome/views/native_scroll_bar.h"
[email protected]1eb89e82008-08-15 12:27:0329#include "chrome/views/root_view.h"
initial.commit09911bf2008-07-26 23:55:2930#include "chrome/views/view.h"
31#include "chrome/views/view_storage.h"
[email protected]a0dde122008-11-21 20:51:2032#include "chrome/views/widget.h"
[email protected]3e45ba92009-02-20 21:09:0033#endif
initial.commit09911bf2008-07-26 23:55:2934
[email protected]3e45ba92009-02-20 21:09:0035// TODO(port): port the rest of this file.
36#if defined(OS_WIN)
[email protected]d5f942ba2008-09-26 19:30:3437namespace {
38
39BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) {
[email protected]4d0bd102008-10-16 00:26:3040 // Note: erase is required to properly paint some widgets borders. This can
41 // be seen with textfields.
[email protected]d5f942ba2008-09-26 19:30:3442 InvalidateRect(hwnd, NULL, TRUE);
43 return TRUE;
44}
45
46} // namespace
47
initial.commit09911bf2008-07-26 23:55:2948TabContents::TabContents(TabContentsType type)
[email protected]d5f942ba2008-09-26 19:30:3449 : type_(type),
initial.commit09911bf2008-07-26 23:55:2950 delegate_(NULL),
51 controller_(NULL),
[email protected]d5f942ba2008-09-26 19:30:3452 is_loading_(false),
53 is_active_(true),
initial.commit09911bf2008-07-26 23:55:2954 is_crashed_(false),
[email protected]d5f942ba2008-09-26 19:30:3455 waiting_for_response_(false),
[email protected]d5f942ba2008-09-26 19:30:3456 shelf_visible_(false),
57 max_page_id_(-1),
[email protected]d6598c052008-11-05 19:03:2558 blocked_popups_(NULL),
[email protected]2d843e62008-11-26 21:16:3559 capturing_contents_(false),
60 is_being_destroyed_(false) {
initial.commit09911bf2008-07-26 23:55:2961 last_focused_view_storage_id_ =
[email protected]c2dacc92008-10-16 23:51:3862 views::ViewStorage::GetSharedInstance()->CreateStorageID();
initial.commit09911bf2008-07-26 23:55:2963}
64
65TabContents::~TabContents() {
66 // Makes sure to remove any stored view we may still have in the ViewStorage.
67 //
68 // It is possible the view went away before us, so we only do this if the
69 // view is registered.
[email protected]c2dacc92008-10-16 23:51:3870 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
initial.commit09911bf2008-07-26 23:55:2971 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
72 view_storage->RemoveView(last_focused_view_storage_id_);
73}
74
[email protected]d5f942ba2008-09-26 19:30:3475// static
76void TabContents::RegisterUserPrefs(PrefService* prefs) {
77 prefs->RegisterBooleanPref(prefs::kBlockPopups, false);
initial.commit09911bf2008-07-26 23:55:2978}
79
initial.commit09911bf2008-07-26 23:55:2980void TabContents::CloseContents() {
81 // Destroy our NavigationController, which will Destroy all tabs it owns.
82 controller_->Destroy();
83 // Note that the controller may have deleted us at this point,
84 // so don't touch any member variables here.
85}
86
87void TabContents::Destroy() {
[email protected]9501428d2008-11-27 01:44:4488 DCHECK(!is_being_destroyed_);
[email protected]2d843e62008-11-26 21:16:3589 is_being_destroyed_ = true;
90
initial.commit09911bf2008-07-26 23:55:2991 // First cleanly close all child windows.
92 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
93 // some of these to close. CloseWindows is async, so it might get called
94 // twice before it runs.
95 int size = static_cast<int>(child_windows_.size());
96 for (int i = size - 1; i >= 0; --i) {
97 ConstrainedWindow* window = child_windows_[i];
98 if (window)
99 window->CloseConstrainedWindow();
100 }
101
[email protected]b6187132009-01-21 23:20:48102 // Notify any lasting InfobarDelegates that have not yet been removed that
103 // whatever infobar they were handling in this TabContents has closed,
104 // because the TabContents is going away entirely.
105 for (int i = 0; i < infobar_delegate_count(); ++i) {
106 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
107 delegate->InfoBarClosed();
108 }
109 infobar_delegates_.clear();
110
initial.commit09911bf2008-07-26 23:55:29111 // Notify any observer that have a reference on this tab contents.
[email protected]bfd04a62009-02-01 18:16:56112 NotificationService::current()->Notify(
113 NotificationType::TAB_CONTENTS_DESTROYED,
114 Source<TabContents>(this),
115 NotificationService::NoDetails());
initial.commit09911bf2008-07-26 23:55:29116
[email protected]92edc472009-02-10 20:32:06117 // If we still have a window handle, destroy it. GetNativeView can return
initial.commit09911bf2008-07-26 23:55:29118 // NULL if this contents was part of a window that closed.
[email protected]92edc472009-02-10 20:32:06119 if (GetNativeView())
120 ::DestroyWindow(GetNativeView());
initial.commit09911bf2008-07-26 23:55:29121
122 // Notify our NavigationController. Make sure we are deleted first, so
123 // that the controller is the last to die.
124 NavigationController* controller = controller_;
125 TabContentsType type = this->type();
126
127 delete this;
128
129 controller->TabContentsWasDestroyed(type);
130}
131
[email protected]d5f942ba2008-09-26 19:30:34132void TabContents::SetupController(Profile* profile) {
133 DCHECK(!controller_);
134 controller_ = new NavigationController(this, profile);
135}
136
137bool TabContents::SupportsURL(GURL* url) {
138 GURL u(*url);
139 if (TabContents::TypeForURL(&u) == type()) {
140 *url = u;
141 return true;
142 }
143 return false;
144}
145
146const GURL& TabContents::GetURL() const {
147 // We may not have a navigation entry yet
148 NavigationEntry* entry = controller_->GetActiveEntry();
149 return entry ? entry->display_url() : GURL::EmptyGURL();
150}
151
[email protected]4c4d8d22009-03-04 05:29:27152const string16& TabContents::GetTitle() const {
[email protected]cbab76d2008-10-13 22:42:47153 // We use the title for the last committed entry rather than a pending
154 // navigation entry. For example, when the user types in a URL, we want to
155 // keep the old page's title until the new load has committed and we get a new
156 // title.
157 // The exception is with transient pages, for which we really want to use
158 // their title, as they are not committed.
159 NavigationEntry* entry = controller_->GetTransientEntry();
[email protected]3d627bbc2008-10-23 20:49:07160 if (entry)
[email protected]4c4d8d22009-03-04 05:29:27161 return entry->GetTitleForDisplay(controller_);
[email protected]f0a51fb52009-03-05 12:46:38162
[email protected]cbab76d2008-10-13 22:42:47163 entry = controller_->GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34164 if (entry)
[email protected]4c4d8d22009-03-04 05:29:27165 return entry->GetTitleForDisplay(controller_);
[email protected]d5f942ba2008-09-26 19:30:34166 else if (controller_->LoadingURLLazily())
167 return controller_->GetLazyTitle();
[email protected]4c4d8d22009-03-04 05:29:27168 return EmptyString16();
[email protected]d5f942ba2008-09-26 19:30:34169}
170
171int32 TabContents::GetMaxPageID() {
172 if (GetSiteInstance())
173 return GetSiteInstance()->max_page_id();
174 else
175 return max_page_id_;
176}
177
178void TabContents::UpdateMaxPageID(int32 page_id) {
179 // Ensure both the SiteInstance and RenderProcessHost update their max page
180 // IDs in sync. Only WebContents will also have site instances, except during
181 // testing.
182 if (GetSiteInstance())
183 GetSiteInstance()->UpdateMaxPageID(page_id);
184
185 if (AsWebContents())
186 AsWebContents()->process()->UpdateMaxPageID(page_id);
187 else
188 max_page_id_ = std::max(max_page_id_, page_id);
189}
190
191const std::wstring TabContents::GetDefaultTitle() const {
192 return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE);
193}
[email protected]3e45ba92009-02-20 21:09:00194#endif // defined(OS_WIN)
[email protected]d5f942ba2008-09-26 19:30:34195
196SkBitmap TabContents::GetFavIcon() const {
197 // Like GetTitle(), we also want to use the favicon for the last committed
198 // entry rather than a pending navigation entry.
[email protected]cbab76d2008-10-13 22:42:47199 NavigationEntry* entry = controller_->GetTransientEntry();
200 if (entry)
201 return entry->favicon().bitmap();
202
203 entry = controller_->GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34204 if (entry)
205 return entry->favicon().bitmap();
206 else if (controller_->LoadingURLLazily())
207 return controller_->GetLazyFavIcon();
208 return SkBitmap();
209}
210
[email protected]3e45ba92009-02-20 21:09:00211#if defined(OS_WIN)
[email protected]d5f942ba2008-09-26 19:30:34212SecurityStyle TabContents::GetSecurityStyle() const {
213 // We may not have a navigation entry yet.
214 NavigationEntry* entry = controller_->GetActiveEntry();
215 return entry ? entry->ssl().security_style() : SECURITY_STYLE_UNKNOWN;
216}
217
218bool TabContents::GetSSLEVText(std::wstring* ev_text,
219 std::wstring* ev_tooltip_text) const {
220 DCHECK(ev_text && ev_tooltip_text);
221 ev_text->clear();
222 ev_tooltip_text->clear();
223
224 NavigationEntry* entry = controller_->GetActiveEntry();
225 if (!entry ||
226 net::IsCertStatusError(entry->ssl().cert_status()) ||
227 ((entry->ssl().cert_status() & net::CERT_STATUS_IS_EV) == 0))
228 return false;
229
230 scoped_refptr<net::X509Certificate> cert;
231 CertStore::GetSharedInstance()->RetrieveCert(entry->ssl().cert_id(), &cert);
232 if (!cert.get()) {
233 NOTREACHED();
234 return false;
235 }
236
237 return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text);
238}
239
240void TabContents::SetIsCrashed(bool state) {
241 if (state == is_crashed_)
242 return;
243
244 is_crashed_ = state;
245 if (delegate_)
246 delegate_->ContentsStateChanged(this);
247}
248
249void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
250 if (delegate_)
251 delegate_->NavigationStateChanged(this, changed_flags);
252}
253
254void TabContents::DidBecomeSelected() {
255 if (controller_)
256 controller_->SetActive(true);
257
258 // Invalidate all descendants. (take care to exclude invalidating ourselves!)
[email protected]92edc472009-02-10 20:32:06259 EnumChildWindows(GetNativeView(), InvalidateWindow, 0);
[email protected]d5f942ba2008-09-26 19:30:34260}
261
262void TabContents::WasHidden() {
[email protected]bfd04a62009-02-01 18:16:56263 NotificationService::current()->Notify(
264 NotificationType::TAB_CONTENTS_HIDDEN,
265 Source<TabContents>(this),
266 NotificationService::NoDetails());
[email protected]d5f942ba2008-09-26 19:30:34267}
268
269void TabContents::Activate() {
270 if (delegate_)
271 delegate_->ActivateContents(this);
272}
273
[email protected]c0588052008-10-27 23:01:50274void TabContents::OpenURL(const GURL& url, const GURL& referrer,
[email protected]d5f942ba2008-09-26 19:30:34275 WindowOpenDisposition disposition,
276 PageTransition::Type transition) {
277 if (delegate_)
[email protected]c0588052008-10-27 23:01:50278 delegate_->OpenURLFromTab(this, url, referrer, disposition, transition);
[email protected]d5f942ba2008-09-26 19:30:34279}
280
281bool TabContents::NavigateToPendingEntry(bool reload) {
282 // Our benavior is just to report that the entry was committed.
283 controller()->GetPendingEntry()->set_title(GetDefaultTitle());
284 controller()->CommitPendingEntry();
285 return true;
286}
287
initial.commit09911bf2008-07-26 23:55:29288ConstrainedWindow* TabContents::CreateConstrainedDialog(
[email protected]c2dacc92008-10-16 23:51:38289 views::WindowDelegate* window_delegate,
290 views::View* contents_view) {
initial.commit09911bf2008-07-26 23:55:29291 ConstrainedWindow* window =
292 ConstrainedWindow::CreateConstrainedDialog(
293 this, gfx::Rect(), contents_view, window_delegate);
294 child_windows_.push_back(window);
295 return window;
296}
297
298void TabContents::AddNewContents(TabContents* new_contents,
299 WindowOpenDisposition disposition,
300 const gfx::Rect& initial_pos,
301 bool user_gesture) {
302 if (!delegate_)
303 return;
304
[email protected]3b0a45e82008-10-13 21:01:03305 if ((disposition == NEW_POPUP) && !user_gesture) {
306 // Unrequested popups from normal pages are constrained.
307 TabContents* popup_owner = this;
308 TabContents* our_owner = delegate_->GetConstrainingContents(this);
309 if (our_owner)
310 popup_owner = our_owner;
311 popup_owner->AddConstrainedPopup(new_contents, initial_pos);
initial.commit09911bf2008-07-26 23:55:29312 } else {
[email protected]0aa55312008-10-17 21:53:08313 new_contents->DisassociateFromPopupCount();
314
initial.commit09911bf2008-07-26 23:55:29315 delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
316 user_gesture);
[email protected]634a6f92008-12-01 21:39:31317
318 PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification());
initial.commit09911bf2008-07-26 23:55:29319 }
320}
321
322void TabContents::AddConstrainedPopup(TabContents* new_contents,
323 const gfx::Rect& initial_pos) {
[email protected]d6598c052008-11-05 19:03:25324 if (!blocked_popups_) {
325 CRect client_rect;
[email protected]92edc472009-02-10 20:32:06326 GetClientRect(GetNativeView(), &client_rect);
[email protected]d6598c052008-11-05 19:03:25327 gfx::Point anchor_position(
328 client_rect.Width() -
329 views::NativeScrollBar::GetVerticalScrollBarWidth(),
330 client_rect.Height());
initial.commit09911bf2008-07-26 23:55:29331
[email protected]d6598c052008-11-05 19:03:25332 blocked_popups_ = BlockedPopupContainer::Create(
333 this, profile(), anchor_position);
334 child_windows_.push_back(blocked_popups_);
335 }
336
337 blocked_popups_->AddTabContents(new_contents, initial_pos);
[email protected]634a6f92008-12-01 21:39:31338 PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification());
initial.commit09911bf2008-07-26 23:55:29339}
340
initial.commit09911bf2008-07-26 23:55:29341void TabContents::CloseAllSuppressedPopups() {
[email protected]d6598c052008-11-05 19:03:25342 if (blocked_popups_)
343 blocked_popups_->CloseAllPopups();
initial.commit09911bf2008-07-26 23:55:29344}
345
initial.commit09911bf2008-07-26 23:55:29346void TabContents::Focus() {
[email protected]92edc472009-02-10 20:32:06347 HWND container_hwnd = GetNativeView();
[email protected]be3877f2009-01-14 15:51:10348 if (!container_hwnd)
349 return;
350
[email protected]c2dacc92008-10-16 23:51:38351 views::FocusManager* focus_manager =
[email protected]be3877f2009-01-14 15:51:10352 views::FocusManager::GetFocusManager(container_hwnd);
initial.commit09911bf2008-07-26 23:55:29353 DCHECK(focus_manager);
[email protected]be3877f2009-01-14 15:51:10354 views::View* v = focus_manager->GetViewForWindow(container_hwnd, true);
initial.commit09911bf2008-07-26 23:55:29355 DCHECK(v);
356 if (v)
357 v->RequestFocus();
358}
359
360void TabContents::StoreFocus() {
[email protected]c2dacc92008-10-16 23:51:38361 views::ViewStorage* view_storage =
362 views::ViewStorage::GetSharedInstance();
initial.commit09911bf2008-07-26 23:55:29363
364 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
365 view_storage->RemoveView(last_focused_view_storage_id_);
366
[email protected]c2dacc92008-10-16 23:51:38367 views::FocusManager* focus_manager =
[email protected]92edc472009-02-10 20:32:06368 views::FocusManager::GetFocusManager(GetNativeView());
initial.commit09911bf2008-07-26 23:55:29369 if (focus_manager) {
370 // |focus_manager| can be NULL if the tab has been detached but still
371 // exists.
[email protected]c2dacc92008-10-16 23:51:38372 views::View* focused_view = focus_manager->GetFocusedView();
initial.commit09911bf2008-07-26 23:55:29373 if (focused_view)
374 view_storage->StoreView(last_focused_view_storage_id_, focused_view);
375
376 // If the focus was on the page, explicitly clear the focus so that we
377 // don't end up with the focused HWND not part of the window hierarchy.
[email protected]c80c5632008-10-10 20:34:35378 // TODO(brettw) this should move to the view somehow.
[email protected]92edc472009-02-10 20:32:06379 HWND container_hwnd = GetNativeView();
initial.commit09911bf2008-07-26 23:55:29380 if (container_hwnd) {
[email protected]c2dacc92008-10-16 23:51:38381 views::View* focused_view = focus_manager->GetFocusedView();
initial.commit09911bf2008-07-26 23:55:29382 if (focused_view) {
[email protected]a0dde122008-11-21 20:51:20383 HWND hwnd = focused_view->GetRootView()->GetWidget()->GetHWND();
initial.commit09911bf2008-07-26 23:55:29384 if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd))
385 focus_manager->ClearFocus();
386 }
387 }
388 }
389}
390
391void TabContents::RestoreFocus() {
[email protected]c2dacc92008-10-16 23:51:38392 views::ViewStorage* view_storage =
393 views::ViewStorage::GetSharedInstance();
394 views::View* last_focused_view =
initial.commit09911bf2008-07-26 23:55:29395 view_storage->RetrieveView(last_focused_view_storage_id_);
396
397 if (!last_focused_view) {
398 SetInitialFocus();
399 } else {
[email protected]c2dacc92008-10-16 23:51:38400 views::FocusManager* focus_manager =
[email protected]92edc472009-02-10 20:32:06401 views::FocusManager::GetFocusManager(GetNativeView());
[email protected]6e2f2cec2008-09-23 22:59:06402
403 // If you hit this DCHECK, please report it to Jay (jcampan).
404 DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";
405
[email protected]830e2062009-02-13 18:27:38406 if (last_focused_view->IsFocusable() && focus_manager &&
407 focus_manager->ContainsView(last_focused_view)) {
initial.commit09911bf2008-07-26 23:55:29408 last_focused_view->RequestFocus();
409 } else {
[email protected]830e2062009-02-13 18:27:38410 // The focused view may not belong to the same window hierarchy (e.g.
411 // if the location bar was focused and the tab is dragged out), or it may
412 // no longer be focusable (e.g. if the location bar was focused and then
413 // we switched to fullscreen mode). In that case we default to the
414 // default focus.
initial.commit09911bf2008-07-26 23:55:29415 SetInitialFocus();
416 }
417 view_storage->RemoveView(last_focused_view_storage_id_);
418 }
419}
420
[email protected]d5f942ba2008-09-26 19:30:34421void TabContents::SetInitialFocus() {
[email protected]92edc472009-02-10 20:32:06422 ::SetFocus(GetNativeView());
initial.commit09911bf2008-07-26 23:55:29423}
424
[email protected]616ed5a2008-11-21 22:27:24425void TabContents::AddInfoBar(InfoBarDelegate* delegate) {
426 // Look through the existing InfoBarDelegates we have for a match. If we've
427 // already got one that matches, then we don't add the new one.
[email protected]f86a07022008-11-25 01:06:05428 for (int i = 0; i < infobar_delegate_count(); ++i) {
[email protected]616ed5a2008-11-21 22:27:24429 if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate))
430 return;
431 }
432
433 infobar_delegates_.push_back(delegate);
[email protected]bfd04a62009-02-01 18:16:56434 NotificationService::current()->Notify(
435 NotificationType::TAB_CONTENTS_INFOBAR_ADDED,
436 Source<TabContents>(this),
437 Details<InfoBarDelegate>(delegate));
[email protected]616ed5a2008-11-21 22:27:24438
439 // Add ourselves as an observer for navigations the first time a delegate is
440 // added. We use this notification to expire InfoBars that need to expire on
441 // page transitions.
442 if (infobar_delegates_.size() == 1) {
[email protected]6a02963e2009-01-06 16:58:03443 DCHECK(controller());
[email protected]bfd04a62009-02-01 18:16:56444 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
[email protected]6a02963e2009-01-06 16:58:03445 Source<NavigationController>(controller()));
[email protected]616ed5a2008-11-21 22:27:24446 }
447}
448
449void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) {
450 std::vector<InfoBarDelegate*>::iterator it =
451 find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate);
452 if (it != infobar_delegates_.end()) {
453 InfoBarDelegate* delegate = *it;
[email protected]bfd04a62009-02-01 18:16:56454 NotificationService::current()->Notify(
455 NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
456 Source<TabContents>(this),
457 Details<InfoBarDelegate>(delegate));
[email protected]f86a07022008-11-25 01:06:05458 infobar_delegates_.erase(it);
[email protected]616ed5a2008-11-21 22:27:24459
[email protected]6a02963e2009-01-06 16:58:03460 // Remove ourselves as an observer if we are tracking no more InfoBars.
461 if (infobar_delegates_.empty()) {
[email protected]bfd04a62009-02-01 18:16:56462 registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED,
[email protected]6a02963e2009-01-06 16:58:03463 Source<NavigationController>(controller()));
464 }
[email protected]616ed5a2008-11-21 22:27:24465 }
466}
[email protected]3edd9522009-03-04 22:19:41467#endif // defined(OS_WIN)
468
469void TabContents::ToolbarSizeChanged(bool is_animating) {
470 TabContentsDelegate* d = delegate();
471 if (d)
472 d->ToolbarSizeChanged(this, is_animating);
473}
[email protected]616ed5a2008-11-21 22:27:24474
initial.commit09911bf2008-07-26 23:55:29475void TabContents::SetDownloadShelfVisible(bool visible) {
476 if (shelf_visible_ != visible) {
477 if (visible) {
[email protected]bcef0dc02009-02-28 00:35:02478 // Invoke GetDownloadShelf to force the shelf to be created.
479 GetDownloadShelf();
initial.commit09911bf2008-07-26 23:55:29480 }
481 shelf_visible_ = visible;
482
[email protected]019d83502008-07-30 22:44:50483 if (delegate_)
484 delegate_->ContentsStateChanged(this);
initial.commit09911bf2008-07-26 23:55:29485 }
[email protected]ce2390b682008-08-08 22:24:51486
487 // SetShelfVisible can force-close the shelf, so make sure we lay out
488 // everything correctly, as if the animation had finished. This doesn't
489 // matter for showing the shelf, as the show animation will do it.
490 ToolbarSizeChanged(false);
initial.commit09911bf2008-07-26 23:55:29491}
492
[email protected]3edd9522009-03-04 22:19:41493#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]d5f942ba2008-09-26 19:30:34494void TabContents::OnStartDownload(DownloadItem* download) {
495 DCHECK(download);
496 TabContents* tab_contents = this;
497
[email protected]3edd9522009-03-04 22:19:41498// TODO(port): port contraining contents.
499#if defined(OS_WIN)
[email protected]d5f942ba2008-09-26 19:30:34500 // Download in a constrained popup is shown in the tab that opened it.
501 TabContents* constraining_tab = delegate()->GetConstrainingContents(this);
502 if (constraining_tab)
503 tab_contents = constraining_tab;
[email protected]3edd9522009-03-04 22:19:41504#endif
[email protected]d5f942ba2008-09-26 19:30:34505
[email protected]bcef0dc02009-02-28 00:35:02506 // GetDownloadShelf creates the download shelf if it was not yet created.
507 tab_contents->GetDownloadShelf()->AddDownload(
508 new DownloadItemModel(download));
[email protected]d5f942ba2008-09-26 19:30:34509 tab_contents->SetDownloadShelfVisible(true);
510
[email protected]3edd9522009-03-04 22:19:41511// TODO(port): port animatinos.
512#if defined(OS_WIN)
[email protected]d5f942ba2008-09-26 19:30:34513 // This animation will delete itself when it finishes, or if we become hidden
514 // or destroyed.
[email protected]92edc472009-02-10 20:32:06515 if (IsWindowVisible(GetNativeView())) { // For minimized windows, unit
516 // tests, etc.
[email protected]d5f942ba2008-09-26 19:30:34517 new DownloadStartedAnimation(tab_contents);
518 }
[email protected]3edd9522009-03-04 22:19:41519#endif
[email protected]d5f942ba2008-09-26 19:30:34520}
521
[email protected]bcef0dc02009-02-28 00:35:02522DownloadShelf* TabContents::GetDownloadShelf() {
523 if (!download_shelf_.get())
524 download_shelf_.reset(DownloadShelf::Create(this));
525 return download_shelf_.get();
initial.commit09911bf2008-07-26 23:55:29526}
527
[email protected]bcef0dc02009-02-28 00:35:02528void TabContents::MigrateShelfFrom(TabContents* tab_contents) {
529 download_shelf_.reset(tab_contents->GetDownloadShelf());
530 download_shelf_->ChangeTabContents(tab_contents, this);
531 tab_contents->ReleaseDownloadShelf();
initial.commit09911bf2008-07-26 23:55:29532}
533
[email protected]3edd9522009-03-04 22:19:41534void TabContents::ReleaseDownloadShelf() {
535 download_shelf_.release();
536}
537
538// static
539void TabContents::MigrateShelf(TabContents* from, TabContents* to) {
540 bool was_shelf_visible = from->IsDownloadShelfVisible();
541 if (was_shelf_visible)
542 to->MigrateShelfFrom(from);
543 to->SetDownloadShelfVisible(was_shelf_visible);
544}
545#endif // defined(OS_WIN) || defined(OS_LINUX)
546
547#if defined(OS_WIN)
[email protected]d5f942ba2008-09-26 19:30:34548void TabContents::WillClose(ConstrainedWindow* window) {
549 ConstrainedWindowList::iterator it =
550 find(child_windows_.begin(), child_windows_.end(), window);
551 if (it != child_windows_.end())
552 child_windows_.erase(it);
553
[email protected]d6598c052008-11-05 19:03:25554 if (window == blocked_popups_)
555 blocked_popups_ = NULL;
556
[email protected]92edc472009-02-10 20:32:06557 if (::IsWindow(GetNativeView())) {
[email protected]d5f942ba2008-09-26 19:30:34558 CRect client_rect;
[email protected]92edc472009-02-10 20:32:06559 GetClientRect(GetNativeView(), &client_rect);
[email protected]d5f942ba2008-09-26 19:30:34560 RepositionSupressedPopupsToFit(
561 gfx::Size(client_rect.Width(), client_rect.Height()));
562 }
563}
564
[email protected]d5f942ba2008-09-26 19:30:34565void TabContents::DidMoveOrResize(ConstrainedWindow* window) {
[email protected]92edc472009-02-10 20:32:06566 UpdateWindow(GetNativeView());
[email protected]d5f942ba2008-09-26 19:30:34567}
568
[email protected]616ed5a2008-11-21 22:27:24569void TabContents::Observe(NotificationType type,
570 const NotificationSource& source,
571 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:56572 DCHECK(type == NotificationType::NAV_ENTRY_COMMITTED);
[email protected]616ed5a2008-11-21 22:27:24573 DCHECK(controller() == Source<NavigationController>(source).ptr());
574
575 NavigationController::LoadCommittedDetails& committed_details =
576 *(Details<NavigationController::LoadCommittedDetails>(details).ptr());
577 ExpireInfoBars(committed_details);
578}
579
[email protected]d5f942ba2008-09-26 19:30:34580void TabContents::SetIsLoading(bool is_loading,
581 LoadNotificationDetails* details) {
582 if (is_loading == is_loading_)
583 return;
584
585 is_loading_ = is_loading;
586 waiting_for_response_ = is_loading;
587
588 // Suppress notifications for this TabContents if we are not active.
589 if (!is_active_)
590 return;
591
592 if (delegate_)
593 delegate_->LoadingStateChanged(this);
594
[email protected]bfd04a62009-02-01 18:16:56595 NotificationType type = is_loading ? NotificationType::LOAD_START :
596 NotificationType::LOAD_STOP;
597 NotificationDetails det = details ?
598 Details<LoadNotificationDetails>(details) :
599 NotificationService::NoDetails();
[email protected]f0a51fb52009-03-05 12:46:38600 NotificationService::current()->Notify(type,
[email protected]bfd04a62009-02-01 18:16:56601 Source<NavigationController>(this->controller()),
602 det);
initial.commit09911bf2008-07-26 23:55:29603}
license.botbf09a502008-08-24 00:55:55604
[email protected]9e0534b2008-10-21 15:03:01605// TODO(brettw) This should be on the WebContentsView.
[email protected]d5f942ba2008-09-26 19:30:34606void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) {
607 // TODO(erg): There's no way to detect whether scroll bars are
608 // visible, so for beta, we're just going to assume that the
609 // vertical scroll bar is visible, and not care about covering up
610 // the horizontal scroll bar. Fixing this is half of
611 // http://b/1118139.
612 gfx::Point anchor_position(
613 new_size.width() -
[email protected]c2dacc92008-10-16 23:51:38614 views::NativeScrollBar::GetVerticalScrollBarWidth(),
[email protected]d5f942ba2008-09-26 19:30:34615 new_size.height());
[email protected]d6598c052008-11-05 19:03:25616
617 if (blocked_popups_)
618 blocked_popups_->RepositionConstrainedWindowTo(anchor_position);
[email protected]d5f942ba2008-09-26 19:30:34619}
620
[email protected]b9681312008-11-07 00:08:26621bool TabContents::ShowingBlockedPopupNotification() const {
622 return blocked_popups_ != NULL &&
623 blocked_popups_->GetTabContentsCount() != 0;
624}
[email protected]616ed5a2008-11-21 22:27:24625
626namespace {
627bool TransitionIsReload(PageTransition::Type transition) {
628 return PageTransition::StripQualifier(transition) == PageTransition::RELOAD;
629}
630}
631
632void TabContents::ExpireInfoBars(
633 const NavigationController::LoadCommittedDetails& details) {
634 // Only hide InfoBars when the user has done something that makes the main
635 // frame load. We don't want various automatic or subframe navigations making
636 // it disappear.
637 if (!details.is_user_initiated_main_frame_load())
638 return;
639
[email protected]f86a07022008-11-25 01:06:05640 for (int i = infobar_delegate_count() - 1; i >= 0; --i) {
[email protected]616ed5a2008-11-21 22:27:24641 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
[email protected]f86a07022008-11-25 01:06:05642 if (delegate->ShouldExpire(details))
[email protected]616ed5a2008-11-21 22:27:24643 RemoveInfoBar(delegate);
[email protected]616ed5a2008-11-21 22:27:24644 }
645}
[email protected]3e45ba92009-02-20 21:09:00646#endif // defined(OS_WIN)