blob: 8afcfef5166231edf01ebcba0d988c3da6eae4ad [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]f3ec7742009-01-15 00:59:165#include "chrome/browser/tab_contents/tab_contents.h"
initial.commit09911bf2008-07-26 23:55:296
7#include "chrome/browser/cert_store.h"
initial.commit09911bf2008-07-26 23:55:298#include "chrome/browser/views/download_shelf_view.h"
9#include "chrome/browser/views/download_started_animation.h"
[email protected]d6598c052008-11-05 19:03:2510#include "chrome/browser/views/blocked_popup_container.h"
[email protected]f3ec7742009-01-15 00:59:1611#include "chrome/browser/tab_contents/infobar_delegate.h"
12#include "chrome/browser/tab_contents/navigation_entry.h"
13#include "chrome/browser/tab_contents/tab_contents_delegate.h"
14#include "chrome/browser/tab_contents/web_contents.h"
[email protected]a4feef82008-10-02 15:11:2215#include "chrome/common/l10n_util.h"
initial.commit09911bf2008-07-26 23:55:2916#include "chrome/common/pref_names.h"
[email protected]1eb89e82008-08-15 12:27:0317#include "chrome/common/pref_service.h"
initial.commit09911bf2008-07-26 23:55:2918#include "chrome/views/native_scroll_bar.h"
[email protected]1eb89e82008-08-15 12:27:0319#include "chrome/views/root_view.h"
initial.commit09911bf2008-07-26 23:55:2920#include "chrome/views/view.h"
21#include "chrome/views/view_storage.h"
[email protected]a0dde122008-11-21 20:51:2022#include "chrome/views/widget.h"
initial.commit09911bf2008-07-26 23:55:2923
24#include "generated_resources.h"
25
[email protected]d5f942ba2008-09-26 19:30:3426namespace {
27
28BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) {
[email protected]4d0bd102008-10-16 00:26:3029 // Note: erase is required to properly paint some widgets borders. This can
30 // be seen with textfields.
[email protected]d5f942ba2008-09-26 19:30:3431 InvalidateRect(hwnd, NULL, TRUE);
32 return TRUE;
33}
34
35} // namespace
36
initial.commit09911bf2008-07-26 23:55:2937TabContents::TabContents(TabContentsType type)
[email protected]d5f942ba2008-09-26 19:30:3438 : type_(type),
initial.commit09911bf2008-07-26 23:55:2939 delegate_(NULL),
40 controller_(NULL),
[email protected]d5f942ba2008-09-26 19:30:3441 is_loading_(false),
42 is_active_(true),
initial.commit09911bf2008-07-26 23:55:2943 is_crashed_(false),
[email protected]d5f942ba2008-09-26 19:30:3444 waiting_for_response_(false),
[email protected]d5f942ba2008-09-26 19:30:3445 shelf_visible_(false),
46 max_page_id_(-1),
[email protected]d6598c052008-11-05 19:03:2547 blocked_popups_(NULL),
[email protected]2d843e62008-11-26 21:16:3548 capturing_contents_(false),
49 is_being_destroyed_(false) {
initial.commit09911bf2008-07-26 23:55:2950 last_focused_view_storage_id_ =
[email protected]c2dacc92008-10-16 23:51:3851 views::ViewStorage::GetSharedInstance()->CreateStorageID();
initial.commit09911bf2008-07-26 23:55:2952}
53
54TabContents::~TabContents() {
55 // Makes sure to remove any stored view we may still have in the ViewStorage.
56 //
57 // It is possible the view went away before us, so we only do this if the
58 // view is registered.
[email protected]c2dacc92008-10-16 23:51:3859 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
initial.commit09911bf2008-07-26 23:55:2960 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
61 view_storage->RemoveView(last_focused_view_storage_id_);
62}
63
[email protected]d5f942ba2008-09-26 19:30:3464// static
65void TabContents::RegisterUserPrefs(PrefService* prefs) {
66 prefs->RegisterBooleanPref(prefs::kBlockPopups, false);
initial.commit09911bf2008-07-26 23:55:2967}
68
initial.commit09911bf2008-07-26 23:55:2969void TabContents::CloseContents() {
70 // Destroy our NavigationController, which will Destroy all tabs it owns.
71 controller_->Destroy();
72 // Note that the controller may have deleted us at this point,
73 // so don't touch any member variables here.
74}
75
76void TabContents::Destroy() {
[email protected]9501428d2008-11-27 01:44:4477 DCHECK(!is_being_destroyed_);
[email protected]2d843e62008-11-26 21:16:3578 is_being_destroyed_ = true;
79
initial.commit09911bf2008-07-26 23:55:2980 // First cleanly close all child windows.
81 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
82 // some of these to close. CloseWindows is async, so it might get called
83 // twice before it runs.
84 int size = static_cast<int>(child_windows_.size());
85 for (int i = size - 1; i >= 0; --i) {
86 ConstrainedWindow* window = child_windows_[i];
87 if (window)
88 window->CloseConstrainedWindow();
89 }
90
[email protected]b6187132009-01-21 23:20:4891 // Notify any lasting InfobarDelegates that have not yet been removed that
92 // whatever infobar they were handling in this TabContents has closed,
93 // because the TabContents is going away entirely.
94 for (int i = 0; i < infobar_delegate_count(); ++i) {
95 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
96 delegate->InfoBarClosed();
97 }
98 infobar_delegates_.clear();
99
initial.commit09911bf2008-07-26 23:55:29100 // Notify any observer that have a reference on this tab contents.
101 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED,
102 Source<TabContents>(this),
103 NotificationService::NoDetails());
104
105 // If we still have a window handle, destroy it. GetContainerHWND can return
106 // NULL if this contents was part of a window that closed.
107 if (GetContainerHWND())
108 ::DestroyWindow(GetContainerHWND());
109
110 // Notify our NavigationController. Make sure we are deleted first, so
111 // that the controller is the last to die.
112 NavigationController* controller = controller_;
113 TabContentsType type = this->type();
114
115 delete this;
116
117 controller->TabContentsWasDestroyed(type);
118}
119
[email protected]d5f942ba2008-09-26 19:30:34120void TabContents::SetupController(Profile* profile) {
121 DCHECK(!controller_);
122 controller_ = new NavigationController(this, profile);
123}
124
125bool TabContents::SupportsURL(GURL* url) {
126 GURL u(*url);
127 if (TabContents::TypeForURL(&u) == type()) {
128 *url = u;
129 return true;
130 }
131 return false;
132}
133
134const GURL& TabContents::GetURL() const {
135 // We may not have a navigation entry yet
136 NavigationEntry* entry = controller_->GetActiveEntry();
137 return entry ? entry->display_url() : GURL::EmptyGURL();
138}
139
140const std::wstring& TabContents::GetTitle() const {
[email protected]cbab76d2008-10-13 22:42:47141 // We use the title for the last committed entry rather than a pending
142 // navigation entry. For example, when the user types in a URL, we want to
143 // keep the old page's title until the new load has committed and we get a new
144 // title.
145 // The exception is with transient pages, for which we really want to use
146 // their title, as they are not committed.
147 NavigationEntry* entry = controller_->GetTransientEntry();
[email protected]3d627bbc2008-10-23 20:49:07148 if (entry)
149 return entry->GetTitleForDisplay();
[email protected]cbab76d2008-10-13 22:42:47150
151 entry = controller_->GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34152 if (entry)
[email protected]3d627bbc2008-10-23 20:49:07153 return entry->GetTitleForDisplay();
[email protected]d5f942ba2008-09-26 19:30:34154 else if (controller_->LoadingURLLazily())
155 return controller_->GetLazyTitle();
156 return EmptyWString();
157}
158
159int32 TabContents::GetMaxPageID() {
160 if (GetSiteInstance())
161 return GetSiteInstance()->max_page_id();
162 else
163 return max_page_id_;
164}
165
166void TabContents::UpdateMaxPageID(int32 page_id) {
167 // Ensure both the SiteInstance and RenderProcessHost update their max page
168 // IDs in sync. Only WebContents will also have site instances, except during
169 // testing.
170 if (GetSiteInstance())
171 GetSiteInstance()->UpdateMaxPageID(page_id);
172
173 if (AsWebContents())
174 AsWebContents()->process()->UpdateMaxPageID(page_id);
175 else
176 max_page_id_ = std::max(max_page_id_, page_id);
177}
178
179const std::wstring TabContents::GetDefaultTitle() const {
180 return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE);
181}
182
183SkBitmap TabContents::GetFavIcon() const {
184 // Like GetTitle(), we also want to use the favicon for the last committed
185 // entry rather than a pending navigation entry.
[email protected]cbab76d2008-10-13 22:42:47186 NavigationEntry* entry = controller_->GetTransientEntry();
187 if (entry)
188 return entry->favicon().bitmap();
189
190 entry = controller_->GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34191 if (entry)
192 return entry->favicon().bitmap();
193 else if (controller_->LoadingURLLazily())
194 return controller_->GetLazyFavIcon();
195 return SkBitmap();
196}
197
198SecurityStyle TabContents::GetSecurityStyle() const {
199 // We may not have a navigation entry yet.
200 NavigationEntry* entry = controller_->GetActiveEntry();
201 return entry ? entry->ssl().security_style() : SECURITY_STYLE_UNKNOWN;
202}
203
204bool TabContents::GetSSLEVText(std::wstring* ev_text,
205 std::wstring* ev_tooltip_text) const {
206 DCHECK(ev_text && ev_tooltip_text);
207 ev_text->clear();
208 ev_tooltip_text->clear();
209
210 NavigationEntry* entry = controller_->GetActiveEntry();
211 if (!entry ||
212 net::IsCertStatusError(entry->ssl().cert_status()) ||
213 ((entry->ssl().cert_status() & net::CERT_STATUS_IS_EV) == 0))
214 return false;
215
216 scoped_refptr<net::X509Certificate> cert;
217 CertStore::GetSharedInstance()->RetrieveCert(entry->ssl().cert_id(), &cert);
218 if (!cert.get()) {
219 NOTREACHED();
220 return false;
221 }
222
223 return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text);
224}
225
226void TabContents::SetIsCrashed(bool state) {
227 if (state == is_crashed_)
228 return;
229
230 is_crashed_ = state;
231 if (delegate_)
232 delegate_->ContentsStateChanged(this);
233}
234
235void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
236 if (delegate_)
237 delegate_->NavigationStateChanged(this, changed_flags);
238}
239
240void TabContents::DidBecomeSelected() {
241 if (controller_)
242 controller_->SetActive(true);
243
244 // Invalidate all descendants. (take care to exclude invalidating ourselves!)
245 EnumChildWindows(GetContainerHWND(), InvalidateWindow, 0);
246}
247
248void TabContents::WasHidden() {
249 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_HIDDEN,
250 Source<TabContents>(this),
251 NotificationService::NoDetails());
252}
253
254void TabContents::Activate() {
255 if (delegate_)
256 delegate_->ActivateContents(this);
257}
258
[email protected]c0588052008-10-27 23:01:50259void TabContents::OpenURL(const GURL& url, const GURL& referrer,
[email protected]d5f942ba2008-09-26 19:30:34260 WindowOpenDisposition disposition,
261 PageTransition::Type transition) {
262 if (delegate_)
[email protected]c0588052008-10-27 23:01:50263 delegate_->OpenURLFromTab(this, url, referrer, disposition, transition);
[email protected]d5f942ba2008-09-26 19:30:34264}
265
266bool TabContents::NavigateToPendingEntry(bool reload) {
267 // Our benavior is just to report that the entry was committed.
268 controller()->GetPendingEntry()->set_title(GetDefaultTitle());
269 controller()->CommitPendingEntry();
270 return true;
271}
272
initial.commit09911bf2008-07-26 23:55:29273ConstrainedWindow* TabContents::CreateConstrainedDialog(
[email protected]c2dacc92008-10-16 23:51:38274 views::WindowDelegate* window_delegate,
275 views::View* contents_view) {
initial.commit09911bf2008-07-26 23:55:29276 ConstrainedWindow* window =
277 ConstrainedWindow::CreateConstrainedDialog(
278 this, gfx::Rect(), contents_view, window_delegate);
279 child_windows_.push_back(window);
280 return window;
281}
282
283void TabContents::AddNewContents(TabContents* new_contents,
284 WindowOpenDisposition disposition,
285 const gfx::Rect& initial_pos,
286 bool user_gesture) {
287 if (!delegate_)
288 return;
289
[email protected]3b0a45e82008-10-13 21:01:03290 if ((disposition == NEW_POPUP) && !user_gesture) {
291 // Unrequested popups from normal pages are constrained.
292 TabContents* popup_owner = this;
293 TabContents* our_owner = delegate_->GetConstrainingContents(this);
294 if (our_owner)
295 popup_owner = our_owner;
296 popup_owner->AddConstrainedPopup(new_contents, initial_pos);
initial.commit09911bf2008-07-26 23:55:29297 } else {
[email protected]0aa55312008-10-17 21:53:08298 new_contents->DisassociateFromPopupCount();
299
initial.commit09911bf2008-07-26 23:55:29300 delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
301 user_gesture);
[email protected]634a6f92008-12-01 21:39:31302
303 PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification());
initial.commit09911bf2008-07-26 23:55:29304 }
305}
306
307void TabContents::AddConstrainedPopup(TabContents* new_contents,
308 const gfx::Rect& initial_pos) {
[email protected]d6598c052008-11-05 19:03:25309 if (!blocked_popups_) {
310 CRect client_rect;
311 GetClientRect(GetContainerHWND(), &client_rect);
312 gfx::Point anchor_position(
313 client_rect.Width() -
314 views::NativeScrollBar::GetVerticalScrollBarWidth(),
315 client_rect.Height());
initial.commit09911bf2008-07-26 23:55:29316
[email protected]d6598c052008-11-05 19:03:25317 blocked_popups_ = BlockedPopupContainer::Create(
318 this, profile(), anchor_position);
319 child_windows_.push_back(blocked_popups_);
320 }
321
322 blocked_popups_->AddTabContents(new_contents, initial_pos);
[email protected]634a6f92008-12-01 21:39:31323 PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification());
initial.commit09911bf2008-07-26 23:55:29324}
325
initial.commit09911bf2008-07-26 23:55:29326void TabContents::CloseAllSuppressedPopups() {
[email protected]d6598c052008-11-05 19:03:25327 if (blocked_popups_)
328 blocked_popups_->CloseAllPopups();
initial.commit09911bf2008-07-26 23:55:29329}
330
initial.commit09911bf2008-07-26 23:55:29331void TabContents::Focus() {
[email protected]be3877f2009-01-14 15:51:10332 HWND container_hwnd = GetContainerHWND();
333 if (!container_hwnd)
334 return;
335
[email protected]c2dacc92008-10-16 23:51:38336 views::FocusManager* focus_manager =
[email protected]be3877f2009-01-14 15:51:10337 views::FocusManager::GetFocusManager(container_hwnd);
initial.commit09911bf2008-07-26 23:55:29338 DCHECK(focus_manager);
[email protected]be3877f2009-01-14 15:51:10339 views::View* v = focus_manager->GetViewForWindow(container_hwnd, true);
initial.commit09911bf2008-07-26 23:55:29340 DCHECK(v);
341 if (v)
342 v->RequestFocus();
343}
344
345void TabContents::StoreFocus() {
[email protected]c2dacc92008-10-16 23:51:38346 views::ViewStorage* view_storage =
347 views::ViewStorage::GetSharedInstance();
initial.commit09911bf2008-07-26 23:55:29348
349 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
350 view_storage->RemoveView(last_focused_view_storage_id_);
351
[email protected]c2dacc92008-10-16 23:51:38352 views::FocusManager* focus_manager =
353 views::FocusManager::GetFocusManager(GetContainerHWND());
initial.commit09911bf2008-07-26 23:55:29354 if (focus_manager) {
355 // |focus_manager| can be NULL if the tab has been detached but still
356 // exists.
[email protected]c2dacc92008-10-16 23:51:38357 views::View* focused_view = focus_manager->GetFocusedView();
initial.commit09911bf2008-07-26 23:55:29358 if (focused_view)
359 view_storage->StoreView(last_focused_view_storage_id_, focused_view);
360
361 // If the focus was on the page, explicitly clear the focus so that we
362 // don't end up with the focused HWND not part of the window hierarchy.
[email protected]c80c5632008-10-10 20:34:35363 // TODO(brettw) this should move to the view somehow.
initial.commit09911bf2008-07-26 23:55:29364 HWND container_hwnd = GetContainerHWND();
365 if (container_hwnd) {
[email protected]c2dacc92008-10-16 23:51:38366 views::View* focused_view = focus_manager->GetFocusedView();
initial.commit09911bf2008-07-26 23:55:29367 if (focused_view) {
[email protected]a0dde122008-11-21 20:51:20368 HWND hwnd = focused_view->GetRootView()->GetWidget()->GetHWND();
initial.commit09911bf2008-07-26 23:55:29369 if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd))
370 focus_manager->ClearFocus();
371 }
372 }
373 }
374}
375
376void TabContents::RestoreFocus() {
[email protected]c2dacc92008-10-16 23:51:38377 views::ViewStorage* view_storage =
378 views::ViewStorage::GetSharedInstance();
379 views::View* last_focused_view =
initial.commit09911bf2008-07-26 23:55:29380 view_storage->RetrieveView(last_focused_view_storage_id_);
381
382 if (!last_focused_view) {
383 SetInitialFocus();
384 } else {
[email protected]c2dacc92008-10-16 23:51:38385 views::FocusManager* focus_manager =
386 views::FocusManager::GetFocusManager(GetContainerHWND());
[email protected]6e2f2cec2008-09-23 22:59:06387
388 // If you hit this DCHECK, please report it to Jay (jcampan).
389 DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";
390
391 if (focus_manager && focus_manager->ContainsView(last_focused_view)) {
initial.commit09911bf2008-07-26 23:55:29392 last_focused_view->RequestFocus();
393 } else {
394 // The focused view may not belong to the same window hierarchy (for
395 // example if the location bar was focused and the tab is dragged out).
396 // In that case we default to the default focus.
397 SetInitialFocus();
398 }
399 view_storage->RemoveView(last_focused_view_storage_id_);
400 }
401}
402
[email protected]d5f942ba2008-09-26 19:30:34403void TabContents::SetInitialFocus() {
404 ::SetFocus(GetContainerHWND());
initial.commit09911bf2008-07-26 23:55:29405}
406
[email protected]616ed5a2008-11-21 22:27:24407void TabContents::AddInfoBar(InfoBarDelegate* delegate) {
408 // Look through the existing InfoBarDelegates we have for a match. If we've
409 // already got one that matches, then we don't add the new one.
[email protected]f86a07022008-11-25 01:06:05410 for (int i = 0; i < infobar_delegate_count(); ++i) {
[email protected]616ed5a2008-11-21 22:27:24411 if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate))
412 return;
413 }
414
415 infobar_delegates_.push_back(delegate);
416 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_ADDED,
417 Source<TabContents>(this),
418 Details<InfoBarDelegate>(delegate));
419
420 // Add ourselves as an observer for navigations the first time a delegate is
421 // added. We use this notification to expire InfoBars that need to expire on
422 // page transitions.
423 if (infobar_delegates_.size() == 1) {
[email protected]6a02963e2009-01-06 16:58:03424 DCHECK(controller());
425 registrar_.Add(this, NOTIFY_NAV_ENTRY_COMMITTED,
426 Source<NavigationController>(controller()));
[email protected]616ed5a2008-11-21 22:27:24427 }
428}
429
430void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) {
431 std::vector<InfoBarDelegate*>::iterator it =
432 find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate);
433 if (it != infobar_delegates_.end()) {
434 InfoBarDelegate* delegate = *it;
[email protected]616ed5a2008-11-21 22:27:24435 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED,
436 Source<TabContents>(this),
437 Details<InfoBarDelegate>(delegate));
[email protected]f86a07022008-11-25 01:06:05438 infobar_delegates_.erase(it);
[email protected]616ed5a2008-11-21 22:27:24439
[email protected]6a02963e2009-01-06 16:58:03440 // Remove ourselves as an observer if we are tracking no more InfoBars.
441 if (infobar_delegates_.empty()) {
442 registrar_.Remove(this, NOTIFY_NAV_ENTRY_COMMITTED,
443 Source<NavigationController>(controller()));
444 }
[email protected]616ed5a2008-11-21 22:27:24445 }
446}
447
initial.commit09911bf2008-07-26 23:55:29448void TabContents::SetDownloadShelfVisible(bool visible) {
449 if (shelf_visible_ != visible) {
450 if (visible) {
451 // Invoke GetDownloadShelfView to force the shelf to be created.
452 GetDownloadShelfView();
453 }
454 shelf_visible_ = visible;
455
[email protected]019d83502008-07-30 22:44:50456 if (delegate_)
457 delegate_->ContentsStateChanged(this);
initial.commit09911bf2008-07-26 23:55:29458 }
[email protected]ce2390b682008-08-08 22:24:51459
460 // SetShelfVisible can force-close the shelf, so make sure we lay out
461 // everything correctly, as if the animation had finished. This doesn't
462 // matter for showing the shelf, as the show animation will do it.
463 ToolbarSizeChanged(false);
initial.commit09911bf2008-07-26 23:55:29464}
465
initial.commit09911bf2008-07-26 23:55:29466void TabContents::ToolbarSizeChanged(bool is_animating) {
467 TabContentsDelegate* d = delegate();
468 if (d)
469 d->ToolbarSizeChanged(this, is_animating);
470}
471
[email protected]d5f942ba2008-09-26 19:30:34472void TabContents::OnStartDownload(DownloadItem* download) {
473 DCHECK(download);
474 TabContents* tab_contents = this;
475
476 // Download in a constrained popup is shown in the tab that opened it.
477 TabContents* constraining_tab = delegate()->GetConstrainingContents(this);
478 if (constraining_tab)
479 tab_contents = constraining_tab;
480
481 // GetDownloadShelfView creates the download shelf if it was not yet created.
482 tab_contents->GetDownloadShelfView()->AddDownload(download);
483 tab_contents->SetDownloadShelfVisible(true);
484
485 // This animation will delete itself when it finishes, or if we become hidden
486 // or destroyed.
487 if (IsWindowVisible(GetContainerHWND())) { // For minimized windows, unit
488 // tests, etc.
489 new DownloadStartedAnimation(tab_contents);
490 }
491}
492
initial.commit09911bf2008-07-26 23:55:29493DownloadShelfView* TabContents::GetDownloadShelfView() {
494 if (!download_shelf_view_.get()) {
495 download_shelf_view_.reset(new DownloadShelfView(this));
496 // The TabContents owns the download-shelf.
497 download_shelf_view_->SetParentOwned(false);
498 }
499 return download_shelf_view_.get();
500}
501
502void TabContents::MigrateShelfViewFrom(TabContents* tab_contents) {
503 download_shelf_view_.reset(tab_contents->GetDownloadShelfView());
504 download_shelf_view_->ChangeTabContents(tab_contents, this);
505 tab_contents->ReleaseDownloadShelfView();
506}
507
[email protected]d5f942ba2008-09-26 19:30:34508void TabContents::WillClose(ConstrainedWindow* window) {
509 ConstrainedWindowList::iterator it =
510 find(child_windows_.begin(), child_windows_.end(), window);
511 if (it != child_windows_.end())
512 child_windows_.erase(it);
513
[email protected]d6598c052008-11-05 19:03:25514 if (window == blocked_popups_)
515 blocked_popups_ = NULL;
516
[email protected]d5f942ba2008-09-26 19:30:34517 if (::IsWindow(GetContainerHWND())) {
518 CRect client_rect;
519 GetClientRect(GetContainerHWND(), &client_rect);
520 RepositionSupressedPopupsToFit(
521 gfx::Size(client_rect.Width(), client_rect.Height()));
522 }
523}
524
[email protected]d5f942ba2008-09-26 19:30:34525void TabContents::DidMoveOrResize(ConstrainedWindow* window) {
526 UpdateWindow(GetContainerHWND());
527}
528
[email protected]616ed5a2008-11-21 22:27:24529void TabContents::Observe(NotificationType type,
530 const NotificationSource& source,
531 const NotificationDetails& details) {
532 DCHECK(type == NOTIFY_NAV_ENTRY_COMMITTED);
533 DCHECK(controller() == Source<NavigationController>(source).ptr());
534
535 NavigationController::LoadCommittedDetails& committed_details =
536 *(Details<NavigationController::LoadCommittedDetails>(details).ptr());
537 ExpireInfoBars(committed_details);
538}
539
initial.commit09911bf2008-07-26 23:55:29540// static
541void TabContents::MigrateShelfView(TabContents* from, TabContents* to) {
542 bool was_shelf_visible = from->IsDownloadShelfVisible();
543 if (was_shelf_visible)
544 to->MigrateShelfViewFrom(from);
545 to->SetDownloadShelfVisible(was_shelf_visible);
546}
547
[email protected]d5f942ba2008-09-26 19:30:34548void TabContents::SetIsLoading(bool is_loading,
549 LoadNotificationDetails* details) {
550 if (is_loading == is_loading_)
551 return;
552
553 is_loading_ = is_loading;
554 waiting_for_response_ = is_loading;
555
556 // Suppress notifications for this TabContents if we are not active.
557 if (!is_active_)
558 return;
559
560 if (delegate_)
561 delegate_->LoadingStateChanged(this);
562
563 NotificationService::current()->
564 Notify((is_loading ? NOTIFY_LOAD_START : NOTIFY_LOAD_STOP),
565 Source<NavigationController>(this->controller()),
566 details ? Details<LoadNotificationDetails>(details) :
567 NotificationService::NoDetails());
initial.commit09911bf2008-07-26 23:55:29568}
license.botbf09a502008-08-24 00:55:55569
[email protected]9e0534b2008-10-21 15:03:01570// TODO(brettw) This should be on the WebContentsView.
[email protected]d5f942ba2008-09-26 19:30:34571void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) {
572 // TODO(erg): There's no way to detect whether scroll bars are
573 // visible, so for beta, we're just going to assume that the
574 // vertical scroll bar is visible, and not care about covering up
575 // the horizontal scroll bar. Fixing this is half of
576 // http://b/1118139.
577 gfx::Point anchor_position(
578 new_size.width() -
[email protected]c2dacc92008-10-16 23:51:38579 views::NativeScrollBar::GetVerticalScrollBarWidth(),
[email protected]d5f942ba2008-09-26 19:30:34580 new_size.height());
[email protected]d6598c052008-11-05 19:03:25581
582 if (blocked_popups_)
583 blocked_popups_->RepositionConstrainedWindowTo(anchor_position);
[email protected]d5f942ba2008-09-26 19:30:34584}
585
586void TabContents::ReleaseDownloadShelfView() {
587 download_shelf_view_.release();
588}
[email protected]b9681312008-11-07 00:08:26589
590bool TabContents::ShowingBlockedPopupNotification() const {
591 return blocked_popups_ != NULL &&
592 blocked_popups_->GetTabContentsCount() != 0;
593}
[email protected]616ed5a2008-11-21 22:27:24594
595namespace {
596bool TransitionIsReload(PageTransition::Type transition) {
597 return PageTransition::StripQualifier(transition) == PageTransition::RELOAD;
598}
599}
600
601void TabContents::ExpireInfoBars(
602 const NavigationController::LoadCommittedDetails& details) {
603 // Only hide InfoBars when the user has done something that makes the main
604 // frame load. We don't want various automatic or subframe navigations making
605 // it disappear.
606 if (!details.is_user_initiated_main_frame_load())
607 return;
608
[email protected]f86a07022008-11-25 01:06:05609 for (int i = infobar_delegate_count() - 1; i >= 0; --i) {
[email protected]616ed5a2008-11-21 22:27:24610 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
[email protected]f86a07022008-11-25 01:06:05611 if (delegate->ShouldExpire(details))
[email protected]616ed5a2008-11-21 22:27:24612 RemoveInfoBar(delegate);
[email protected]616ed5a2008-11-21 22:27:24613 }
614}