| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/tab_contents.h" | 5 #include "chrome/browser/tab_contents.h" |
| 6 | 6 |
| 7 #include "chrome/browser/cert_store.h" | 7 #include "chrome/browser/cert_store.h" |
| 8 #include "chrome/browser/navigation_entry.h" | 8 #include "chrome/browser/navigation_entry.h" |
| 9 #include "chrome/browser/views/download_shelf_view.h" | 9 #include "chrome/browser/views/download_shelf_view.h" |
| 10 #include "chrome/browser/views/download_started_animation.h" | 10 #include "chrome/browser/views/download_started_animation.h" |
| 11 #include "chrome/browser/web_contents.h" | 11 #include "chrome/browser/web_contents.h" |
| 12 #include "chrome/browser/tab_contents_delegate.h" | 12 #include "chrome/browser/tab_contents_delegate.h" |
| 13 #include "chrome/common/pref_names.h" | 13 #include "chrome/common/pref_names.h" |
| 14 #include "chrome/common/pref_service.h" | 14 #include "chrome/common/pref_service.h" |
| 15 #include "chrome/views/native_scroll_bar.h" | 15 #include "chrome/views/native_scroll_bar.h" |
| 16 #include "chrome/views/root_view.h" | 16 #include "chrome/views/root_view.h" |
| 17 #include "chrome/views/view.h" | 17 #include "chrome/views/view.h" |
| 18 #include "chrome/views/view_storage.h" | 18 #include "chrome/views/view_storage.h" |
| 19 | 19 |
| 20 #include "generated_resources.h" | 20 #include "generated_resources.h" |
| 21 | 21 |
| 22 namespace { |
| 23 |
| 24 BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) { |
| 25 // Note: erase is required to properly paint some widgets borders. This can be |
| 26 // seen with textfields. |
| 27 InvalidateRect(hwnd, NULL, TRUE); |
| 28 return TRUE; |
| 29 } |
| 30 |
| 31 } // namespace |
| 32 |
| 22 TabContents::TabContents(TabContentsType type) | 33 TabContents::TabContents(TabContentsType type) |
| 23 : is_loading_(false), | 34 : type_(type), |
| 24 response_started_(false), | |
| 25 is_active_(true), | |
| 26 type_(type), | |
| 27 delegate_(NULL), | 35 delegate_(NULL), |
| 28 controller_(NULL), | 36 controller_(NULL), |
| 37 is_loading_(false), |
| 38 is_active_(true), |
| 39 is_crashed_(false), |
| 40 waiting_for_response_(false), |
| 41 saved_location_bar_state_(NULL), |
| 42 shelf_visible_(false), |
| 29 max_page_id_(-1), | 43 max_page_id_(-1), |
| 30 saved_location_bar_state_(NULL), | 44 capturing_contents_(false) { |
| 31 is_crashed_(false), | |
| 32 shelf_visible_(false) { | |
| 33 last_focused_view_storage_id_ = | 45 last_focused_view_storage_id_ = |
| 34 ChromeViews::ViewStorage::GetSharedInstance()->CreateStorageID(); | 46 ChromeViews::ViewStorage::GetSharedInstance()->CreateStorageID(); |
| 35 } | 47 } |
| 36 | 48 |
| 37 TabContents::~TabContents() { | 49 TabContents::~TabContents() { |
| 38 // Makes sure to remove any stored view we may still have in the ViewStorage. | 50 // Makes sure to remove any stored view we may still have in the ViewStorage. |
| 39 // | 51 // |
| 40 // It is possible the view went away before us, so we only do this if the | 52 // It is possible the view went away before us, so we only do this if the |
| 41 // view is registered. | 53 // view is registered. |
| 42 ChromeViews::ViewStorage* view_storage = | 54 ChromeViews::ViewStorage* view_storage = |
| 43 ChromeViews::ViewStorage::GetSharedInstance(); | 55 ChromeViews::ViewStorage::GetSharedInstance(); |
| 44 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) | 56 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) |
| 45 view_storage->RemoveView(last_focused_view_storage_id_); | 57 view_storage->RemoveView(last_focused_view_storage_id_); |
| 46 } | 58 } |
| 47 | 59 |
| 48 void TabContents::HideContents() { | 60 // static |
| 49 // Hide the contents before adjusting its parent to avoid a full desktop | 61 void TabContents::RegisterUserPrefs(PrefService* prefs) { |
| 50 // flicker. | 62 prefs->RegisterBooleanPref(prefs::kBlockPopups, false); |
| 51 ShowWindow(GetContainerHWND(), SW_HIDE); | |
| 52 | |
| 53 // Reset the parent to NULL to ensure hidden tabs don't receive messages. | |
| 54 SetParent(GetContainerHWND(), NULL); | |
| 55 | |
| 56 // Remove any focus manager related information. | |
| 57 ChromeViews::FocusManager::UninstallFocusSubclass(GetContainerHWND()); | |
| 58 | |
| 59 WasHidden(); | |
| 60 } | 63 } |
| 61 | 64 |
| 62 int32 TabContents::GetMaxPageID() { | 65 |
| 63 if (GetSiteInstance()) | 66 void TabContents::CloseContents() { |
| 64 return GetSiteInstance()->max_page_id(); | 67 // Destroy our NavigationController, which will Destroy all tabs it owns. |
| 65 else | 68 controller_->Destroy(); |
| 66 return max_page_id_; | 69 // Note that the controller may have deleted us at this point, |
| 70 // so don't touch any member variables here. |
| 67 } | 71 } |
| 68 | 72 |
| 69 void TabContents::UpdateMaxPageID(int32 page_id) { | 73 void TabContents::Destroy() { |
| 70 // Ensure both the SiteInstance and RenderProcessHost update their max page | 74 // First cleanly close all child windows. |
| 71 // IDs in sync. Only WebContents will also have site instances, except during | 75 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked |
| 72 // testing. | 76 // some of these to close. CloseWindows is async, so it might get called |
| 73 if (GetSiteInstance()) | 77 // twice before it runs. |
| 74 GetSiteInstance()->UpdateMaxPageID(page_id); | 78 int size = static_cast<int>(child_windows_.size()); |
| 79 for (int i = size - 1; i >= 0; --i) { |
| 80 ConstrainedWindow* window = child_windows_[i]; |
| 81 if (window) |
| 82 window->CloseConstrainedWindow(); |
| 83 } |
| 75 | 84 |
| 76 if (AsWebContents()) | 85 // Notify any observer that have a reference on this tab contents. |
| 77 AsWebContents()->process()->UpdateMaxPageID(page_id); | 86 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED, |
| 78 else | 87 Source<TabContents>(this), |
| 79 max_page_id_ = std::max(max_page_id_, page_id); | 88 NotificationService::NoDetails()); |
| 80 } | |
| 81 | 89 |
| 82 const std::wstring TabContents::GetDefaultTitle() const { | 90 // If we still have a window handle, destroy it. GetContainerHWND can return |
| 83 return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE); | 91 // NULL if this contents was part of a window that closed. |
| 92 if (GetContainerHWND()) |
| 93 ::DestroyWindow(GetContainerHWND()); |
| 94 |
| 95 // Notify our NavigationController. Make sure we are deleted first, so |
| 96 // that the controller is the last to die. |
| 97 NavigationController* controller = controller_; |
| 98 TabContentsType type = this->type(); |
| 99 |
| 100 delete this; |
| 101 |
| 102 controller->TabContentsWasDestroyed(type); |
| 84 } | 103 } |
| 85 | 104 |
| 86 void TabContents::SetupController(Profile* profile) { | 105 void TabContents::SetupController(Profile* profile) { |
| 87 DCHECK(!controller_); | 106 DCHECK(!controller_); |
| 88 controller_ = new NavigationController(this, profile); | 107 controller_ = new NavigationController(this, profile); |
| 89 } | 108 } |
| 90 | 109 |
| 110 bool TabContents::SupportsURL(GURL* url) { |
| 111 GURL u(*url); |
| 112 if (TabContents::TypeForURL(&u) == type()) { |
| 113 *url = u; |
| 114 return true; |
| 115 } |
| 116 return false; |
| 117 } |
| 118 |
| 91 const GURL& TabContents::GetURL() const { | 119 const GURL& TabContents::GetURL() const { |
| 92 DCHECK(controller_); | |
| 93 | |
| 94 static const GURL kEmptyURL; | |
| 95 | |
| 96 // We may not have a navigation entry yet | 120 // We may not have a navigation entry yet |
| 97 NavigationEntry* entry = controller_->GetActiveEntry(); | 121 NavigationEntry* entry = controller_->GetActiveEntry(); |
| 98 return entry ? entry->display_url() : kEmptyURL; | 122 return entry ? entry->display_url() : GURL::EmptyGURL(); |
| 99 } | 123 } |
| 100 | 124 |
| 101 const std::wstring& TabContents::GetTitle() const { | 125 const std::wstring& TabContents::GetTitle() const { |
| 102 DCHECK(controller_); | |
| 103 | |
| 104 // We always want to use the title for the last committed entry rather than | 126 // We always want to use the title for the last committed entry rather than |
| 105 // a pending navigation entry. For example, when the user types in a URL, we | 127 // a pending navigation entry. For example, when the user types in a URL, we |
| 106 // want to keep the old page's title until the new load has committed and we | 128 // want to keep the old page's title until the new load has committed and we |
| 107 // get a new title. | 129 // get a new title. |
| 108 NavigationEntry* entry = controller_->GetLastCommittedEntry(); | 130 NavigationEntry* entry = controller_->GetLastCommittedEntry(); |
| 109 if (entry) | 131 if (entry) |
| 110 return entry->title(); | 132 return entry->title(); |
| 111 else if (controller_->LoadingURLLazily()) | 133 else if (controller_->LoadingURLLazily()) |
| 112 return controller_->GetLazyTitle(); | 134 return controller_->GetLazyTitle(); |
| 113 return EmptyWString(); | 135 return EmptyWString(); |
| 114 } | 136 } |
| 115 | 137 |
| 138 int32 TabContents::GetMaxPageID() { |
| 139 if (GetSiteInstance()) |
| 140 return GetSiteInstance()->max_page_id(); |
| 141 else |
| 142 return max_page_id_; |
| 143 } |
| 144 |
| 145 void TabContents::UpdateMaxPageID(int32 page_id) { |
| 146 // Ensure both the SiteInstance and RenderProcessHost update their max page |
| 147 // IDs in sync. Only WebContents will also have site instances, except during |
| 148 // testing. |
| 149 if (GetSiteInstance()) |
| 150 GetSiteInstance()->UpdateMaxPageID(page_id); |
| 151 |
| 152 if (AsWebContents()) |
| 153 AsWebContents()->process()->UpdateMaxPageID(page_id); |
| 154 else |
| 155 max_page_id_ = std::max(max_page_id_, page_id); |
| 156 } |
| 157 |
| 158 const std::wstring TabContents::GetDefaultTitle() const { |
| 159 return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE); |
| 160 } |
| 161 |
| 116 SkBitmap TabContents::GetFavIcon() const { | 162 SkBitmap TabContents::GetFavIcon() const { |
| 117 DCHECK(controller_); | |
| 118 | |
| 119 // Like GetTitle(), we also want to use the favicon for the last committed | 163 // Like GetTitle(), we also want to use the favicon for the last committed |
| 120 // entry rather than a pending navigation entry. | 164 // entry rather than a pending navigation entry. |
| 121 NavigationEntry* entry = controller_->GetLastCommittedEntry(); | 165 NavigationEntry* entry = controller_->GetLastCommittedEntry(); |
| 122 if (entry) | 166 if (entry) |
| 123 return entry->favicon().bitmap(); | 167 return entry->favicon().bitmap(); |
| 124 else if (controller_->LoadingURLLazily()) | 168 else if (controller_->LoadingURLLazily()) |
| 125 return controller_->GetLazyFavIcon(); | 169 return controller_->GetLazyFavIcon(); |
| 126 return SkBitmap(); | 170 return SkBitmap(); |
| 127 } | 171 } |
| 128 | 172 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 147 scoped_refptr<net::X509Certificate> cert; | 191 scoped_refptr<net::X509Certificate> cert; |
| 148 CertStore::GetSharedInstance()->RetrieveCert(entry->ssl().cert_id(), &cert); | 192 CertStore::GetSharedInstance()->RetrieveCert(entry->ssl().cert_id(), &cert); |
| 149 if (!cert.get()) { | 193 if (!cert.get()) { |
| 150 NOTREACHED(); | 194 NOTREACHED(); |
| 151 return false; | 195 return false; |
| 152 } | 196 } |
| 153 | 197 |
| 154 return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text); | 198 return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text); |
| 155 } | 199 } |
| 156 | 200 |
| 157 void TabContents::CloseContents() { | 201 void TabContents::SetIsCrashed(bool state) { |
| 158 // Destroy our NavigationController, which will Destroy all tabs it owns. | 202 if (state == is_crashed_) |
| 159 controller_->Destroy(); | 203 return; |
| 160 // Note that the controller may have deleted us at this point, | 204 |
| 161 // so don't touch any member variables here. | 205 is_crashed_ = state; |
| 206 if (delegate_) |
| 207 delegate_->ContentsStateChanged(this); |
| 162 } | 208 } |
| 163 | 209 |
| 164 void TabContents::Destroy() { | 210 void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) { |
| 165 // First cleanly close all child windows. | 211 if (delegate_) |
| 166 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked | 212 delegate_->NavigationStateChanged(this, changed_flags); |
| 167 // some of these to close. CloseWindows is async, so it might get called | 213 } |
| 168 // twice before it runs. | |
| 169 int size = static_cast<int>(child_windows_.size()); | |
| 170 for (int i = size - 1; i >= 0; --i) { | |
| 171 ConstrainedWindow* window = child_windows_[i]; | |
| 172 if (window) | |
| 173 window->CloseConstrainedWindow(); | |
| 174 } | |
| 175 | 214 |
| 176 // Notify any observer that have a reference on this tab contents. | 215 void TabContents::DidBecomeSelected() { |
| 177 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED, | 216 if (controller_) |
| 217 controller_->SetActive(true); |
| 218 |
| 219 // Invalidate all descendants. (take care to exclude invalidating ourselves!) |
| 220 EnumChildWindows(GetContainerHWND(), InvalidateWindow, 0); |
| 221 } |
| 222 |
| 223 void TabContents::WasHidden() { |
| 224 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_HIDDEN, |
| 178 Source<TabContents>(this), | 225 Source<TabContents>(this), |
| 179 NotificationService::NoDetails()); | 226 NotificationService::NoDetails()); |
| 227 } |
| 180 | 228 |
| 181 // If we still have a window handle, destroy it. GetContainerHWND can return | 229 void TabContents::Activate() { |
| 182 // NULL if this contents was part of a window that closed. | 230 if (delegate_) |
| 183 if (GetContainerHWND()) | 231 delegate_->ActivateContents(this); |
| 184 ::DestroyWindow(GetContainerHWND()); | 232 } |
| 185 | 233 |
| 186 // Notify our NavigationController. Make sure we are deleted first, so | 234 void TabContents::OpenURL(const GURL& url, |
| 187 // that the controller is the last to die. | 235 WindowOpenDisposition disposition, |
| 188 NavigationController* controller = controller_; | 236 PageTransition::Type transition) { |
| 189 TabContentsType type = this->type(); | 237 if (delegate_) |
| 238 delegate_->OpenURLFromTab(this, url, disposition, transition); |
| 239 } |
| 190 | 240 |
| 191 delete this; | 241 bool TabContents::NavigateToPendingEntry(bool reload) { |
| 192 | 242 // Our benavior is just to report that the entry was committed. |
| 193 controller->TabContentsWasDestroyed(type); | 243 controller()->GetPendingEntry()->set_title(GetDefaultTitle()); |
| 244 controller()->CommitPendingEntry(); |
| 245 return true; |
| 194 } | 246 } |
| 195 | 247 |
| 196 ConstrainedWindow* TabContents::CreateConstrainedDialog( | 248 ConstrainedWindow* TabContents::CreateConstrainedDialog( |
| 197 ChromeViews::WindowDelegate* window_delegate, | 249 ChromeViews::WindowDelegate* window_delegate, |
| 198 ChromeViews::View* contents_view) { | 250 ChromeViews::View* contents_view) { |
| 199 ConstrainedWindow* window = | 251 ConstrainedWindow* window = |
| 200 ConstrainedWindow::CreateConstrainedDialog( | 252 ConstrainedWindow::CreateConstrainedDialog( |
| 201 this, gfx::Rect(), contents_view, window_delegate); | 253 this, gfx::Rect(), contents_view, window_delegate); |
| 202 child_windows_.push_back(window); | 254 child_windows_.push_back(window); |
| 203 return window; | 255 return window; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 229 ConstrainedWindow::CreateConstrainedPopup( | 281 ConstrainedWindow::CreateConstrainedPopup( |
| 230 this, initial_pos, new_contents); | 282 this, initial_pos, new_contents); |
| 231 child_windows_.push_back(window); | 283 child_windows_.push_back(window); |
| 232 | 284 |
| 233 CRect client_rect; | 285 CRect client_rect; |
| 234 GetClientRect(GetContainerHWND(), &client_rect); | 286 GetClientRect(GetContainerHWND(), &client_rect); |
| 235 gfx::Size new_size(client_rect.Width(), client_rect.Height()); | 287 gfx::Size new_size(client_rect.Width(), client_rect.Height()); |
| 236 RepositionSupressedPopupsToFit(new_size); | 288 RepositionSupressedPopupsToFit(new_size); |
| 237 } | 289 } |
| 238 | 290 |
| 239 void TabContents::SetIsLoading(bool is_loading, | |
| 240 LoadNotificationDetails* details) { | |
| 241 if (is_loading == is_loading_) | |
| 242 return; | |
| 243 | |
| 244 is_loading_ = is_loading; | |
| 245 response_started_ = is_loading; | |
| 246 | |
| 247 // Suppress notifications for this TabContents if we are not active. | |
| 248 if (!is_active_) | |
| 249 return; | |
| 250 | |
| 251 if (delegate_) | |
| 252 delegate_->LoadingStateChanged(this); | |
| 253 | |
| 254 NotificationService::current()-> | |
| 255 Notify((is_loading ? NOTIFY_LOAD_START : NOTIFY_LOAD_STOP), | |
| 256 Source<NavigationController>(this->controller()), | |
| 257 details ? Details<LoadNotificationDetails>(details) : | |
| 258 NotificationService::NoDetails()); | |
| 259 } | |
| 260 | |
| 261 bool TabContents::NavigateToPendingEntry(bool reload) { | |
| 262 // Our benavior is just to report that the entry was committed. | |
| 263 controller()->GetPendingEntry()->set_title(GetDefaultTitle()); | |
| 264 controller()->CommitPendingEntry(); | |
| 265 return true; | |
| 266 } | |
| 267 | |
| 268 void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) { | |
| 269 if (delegate_) | |
| 270 delegate_->NavigationStateChanged(this, changed_flags); | |
| 271 } | |
| 272 | |
| 273 static BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) { | |
| 274 // Note: erase is required to properly paint some widgets borders. This can be | |
| 275 // seen with textfields. | |
| 276 InvalidateRect(hwnd, NULL, TRUE); | |
| 277 return TRUE; | |
| 278 } | |
| 279 | |
| 280 void TabContents::DidBecomeSelected() { | |
| 281 if (controller_) | |
| 282 controller_->SetActive(true); | |
| 283 | |
| 284 // Invalidate all descendants. (take care to exclude invalidating ourselves!) | |
| 285 EnumChildWindows(GetContainerHWND(), InvalidateWindow, 0); | |
| 286 } | |
| 287 | |
| 288 void TabContents::WasHidden() { | |
| 289 NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_HIDDEN, | |
| 290 Source<TabContents>(this), | |
| 291 NotificationService::NoDetails()); | |
| 292 } | |
| 293 | |
| 294 void TabContents::Activate() { | |
| 295 if (delegate_) | |
| 296 delegate_->ActivateContents(this); | |
| 297 } | |
| 298 | |
| 299 void TabContents::CloseAllSuppressedPopups() { | 291 void TabContents::CloseAllSuppressedPopups() { |
| 300 // Close all auto positioned child windows to "clean up" the workspace. | 292 // Close all auto positioned child windows to "clean up" the workspace. |
| 301 int count = static_cast<int>(child_windows_.size()); | 293 int count = static_cast<int>(child_windows_.size()); |
| 302 for (int i = count - 1; i >= 0; --i) { | 294 for (int i = count - 1; i >= 0; --i) { |
| 303 ConstrainedWindow* window = child_windows_.at(i); | 295 ConstrainedWindow* window = child_windows_.at(i); |
| 304 if (window->IsSuppressedConstrainedWindow()) | 296 if (window->IsSuppressedConstrainedWindow()) |
| 305 window->CloseConstrainedWindow(); | 297 window->CloseConstrainedWindow(); |
| 306 } | 298 } |
| 307 } | 299 } |
| 308 | 300 |
| 309 void TabContents::OnStartDownload(DownloadItem* download) { | 301 void TabContents::HideContents() { |
| 310 DCHECK(download); | 302 // Hide the contents before adjusting its parent to avoid a full desktop |
| 311 TabContents* tab_contents = this; | 303 // flicker. |
| 304 ShowWindow(GetContainerHWND(), SW_HIDE); |
| 312 | 305 |
| 313 // Download in a constrained popup is shown in the tab that opened it. | 306 // Reset the parent to NULL to ensure hidden tabs don't receive messages. |
| 314 TabContents* constraining_tab = delegate()->GetConstrainingContents(this); | 307 SetParent(GetContainerHWND(), NULL); |
| 315 if (constraining_tab) | |
| 316 tab_contents = constraining_tab; | |
| 317 | 308 |
| 318 // GetDownloadShelfView creates the download shelf if it was not yet created. | 309 // Remove any focus manager related information. |
| 319 tab_contents->GetDownloadShelfView()->AddDownload(download); | 310 ChromeViews::FocusManager::UninstallFocusSubclass(GetContainerHWND()); |
| 320 tab_contents->SetDownloadShelfVisible(true); | |
| 321 | 311 |
| 322 // This animation will delete itself when it finishes, or if we become hidden | 312 WasHidden(); |
| 323 // or destroyed. | |
| 324 if (IsWindowVisible(GetContainerHWND())) { // For minimized windows, unit | |
| 325 // tests, etc. | |
| 326 new DownloadStartedAnimation(tab_contents); | |
| 327 } | |
| 328 } | 313 } |
| 329 | 314 |
| 330 | |
| 331 /////////////////////////////////////////////////////////////////////////////// | |
| 332 // TabContents, ConstrainedTabContentsDelegate implementation: | |
| 333 | |
| 334 void TabContents::AddNewContents(ConstrainedWindow* window, | |
| 335 TabContents* new_contents, | |
| 336 WindowOpenDisposition disposition, | |
| 337 const gfx::Rect& initial_pos, | |
| 338 bool user_gesture) { | |
| 339 AddNewContents(new_contents, disposition, initial_pos, user_gesture); | |
| 340 } | |
| 341 | |
| 342 void TabContents::OpenURL(ConstrainedWindow* window, | |
| 343 const GURL& url, | |
| 344 WindowOpenDisposition disposition, | |
| 345 PageTransition::Type transition) { | |
| 346 OpenURL(url, disposition, transition); | |
| 347 } | |
| 348 | |
| 349 void TabContents::WillClose(ConstrainedWindow* window) { | |
| 350 ConstrainedWindowList::iterator it = | |
| 351 find(child_windows_.begin(), child_windows_.end(), window); | |
| 352 if (it != child_windows_.end()) | |
| 353 child_windows_.erase(it); | |
| 354 | |
| 355 if (::IsWindow(GetContainerHWND())) { | |
| 356 CRect client_rect; | |
| 357 GetClientRect(GetContainerHWND(), &client_rect); | |
| 358 RepositionSupressedPopupsToFit( | |
| 359 gfx::Size(client_rect.Width(), client_rect.Height())); | |
| 360 } | |
| 361 } | |
| 362 | |
| 363 void TabContents::DetachContents(ConstrainedWindow* window, | |
| 364 TabContents* contents, | |
| 365 const gfx::Rect& contents_bounds, | |
| 366 const gfx::Point& mouse_pt, | |
| 367 int frame_component) { | |
| 368 WillClose(window); | |
| 369 if (delegate_) { | |
| 370 delegate_->StartDraggingDetachedContents( | |
| 371 this, contents, contents_bounds, mouse_pt, frame_component); | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 void TabContents::DidMoveOrResize(ConstrainedWindow* window) { | |
| 376 UpdateWindow(GetContainerHWND()); | |
| 377 } | |
| 378 | |
| 379 /////////////////////////////////////////////////////////////////////////////// | |
| 380 // PageNavigator methods | |
| 381 | |
| 382 void TabContents::OpenURL(const GURL& url, | |
| 383 WindowOpenDisposition disposition, | |
| 384 PageTransition::Type transition) { | |
| 385 if (delegate_) | |
| 386 delegate_->OpenURLFromTab(this, url, disposition, transition); | |
| 387 } | |
| 388 | |
| 389 /////////////////////////////////////////////////////////////////////////////// | |
| 390 | |
| 391 void TabContents::Focus() { | 315 void TabContents::Focus() { |
| 392 ChromeViews::FocusManager* focus_manager = | 316 ChromeViews::FocusManager* focus_manager = |
| 393 ChromeViews::FocusManager::GetFocusManager(GetContainerHWND()); | 317 ChromeViews::FocusManager::GetFocusManager(GetContainerHWND()); |
| 394 DCHECK(focus_manager); | 318 DCHECK(focus_manager); |
| 395 ChromeViews::View* v = | 319 ChromeViews::View* v = |
| 396 focus_manager->GetViewForWindow(GetContainerHWND(), true); | 320 focus_manager->GetViewForWindow(GetContainerHWND(), true); |
| 397 DCHECK(v); | 321 DCHECK(v); |
| 398 if (v) | 322 if (v) |
| 399 v->RequestFocus(); | 323 v->RequestFocus(); |
| 400 } | 324 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 } else { | 373 } else { |
| 450 // The focused view may not belong to the same window hierarchy (for | 374 // The focused view may not belong to the same window hierarchy (for |
| 451 // example if the location bar was focused and the tab is dragged out). | 375 // example if the location bar was focused and the tab is dragged out). |
| 452 // In that case we default to the default focus. | 376 // In that case we default to the default focus. |
| 453 SetInitialFocus(); | 377 SetInitialFocus(); |
| 454 } | 378 } |
| 455 view_storage->RemoveView(last_focused_view_storage_id_); | 379 view_storage->RemoveView(last_focused_view_storage_id_); |
| 456 } | 380 } |
| 457 } | 381 } |
| 458 | 382 |
| 459 void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) { | 383 void TabContents::SetInitialFocus() { |
| 460 // TODO(erg): There's no way to detect whether scroll bars are | 384 ::SetFocus(GetContainerHWND()); |
| 461 // visible, so for beta, we're just going to assume that the | |
| 462 // vertical scroll bar is visible, and not care about covering up | |
| 463 // the horizontal scroll bar. Fixing this is half of | |
| 464 // http://b/1118139. | |
| 465 gfx::Point anchor_position( | |
| 466 new_size.width() - ChromeViews::NativeScrollBar::GetVerticalScrollBarWidth
(), | |
| 467 new_size.height()); | |
| 468 int window_count = static_cast<int>(child_windows_.size()); | |
| 469 for (int i = window_count - 1; i >= 0; --i) { | |
| 470 ConstrainedWindow* window = child_windows_.at(i); | |
| 471 if (window->IsSuppressedConstrainedWindow()) | |
| 472 window->RepositionConstrainedWindowTo(anchor_position); | |
| 473 } | |
| 474 } | 385 } |
| 475 | 386 |
| 476 void TabContents::SetDownloadShelfVisible(bool visible) { | 387 void TabContents::SetDownloadShelfVisible(bool visible) { |
| 477 if (shelf_visible_ != visible) { | 388 if (shelf_visible_ != visible) { |
| 478 if (visible) { | 389 if (visible) { |
| 479 // Invoke GetDownloadShelfView to force the shelf to be created. | 390 // Invoke GetDownloadShelfView to force the shelf to be created. |
| 480 GetDownloadShelfView(); | 391 GetDownloadShelfView(); |
| 481 } | 392 } |
| 482 shelf_visible_ = visible; | 393 shelf_visible_ = visible; |
| 483 | 394 |
| 484 if (delegate_) | 395 if (delegate_) |
| 485 delegate_->ContentsStateChanged(this); | 396 delegate_->ContentsStateChanged(this); |
| 486 } | 397 } |
| 487 | 398 |
| 488 // SetShelfVisible can force-close the shelf, so make sure we lay out | 399 // SetShelfVisible can force-close the shelf, so make sure we lay out |
| 489 // everything correctly, as if the animation had finished. This doesn't | 400 // everything correctly, as if the animation had finished. This doesn't |
| 490 // matter for showing the shelf, as the show animation will do it. | 401 // matter for showing the shelf, as the show animation will do it. |
| 491 ToolbarSizeChanged(false); | 402 ToolbarSizeChanged(false); |
| 492 } | 403 } |
| 493 | 404 |
| 494 void TabContents::ReleaseDownloadShelfView() { | |
| 495 download_shelf_view_.release(); | |
| 496 } | |
| 497 | |
| 498 void TabContents::SetInitialFocus() { | |
| 499 ::SetFocus(GetContainerHWND()); | |
| 500 } | |
| 501 | |
| 502 void TabContents::SetIsCrashed(bool state) { | |
| 503 if (state == is_crashed_) | |
| 504 return; | |
| 505 | |
| 506 is_crashed_ = state; | |
| 507 if (delegate_) | |
| 508 delegate_->ContentsStateChanged(this); | |
| 509 } | |
| 510 | |
| 511 bool TabContents::IsCrashed() const { | |
| 512 return is_crashed_; | |
| 513 } | |
| 514 | |
| 515 bool TabContents::SupportsURL(GURL* url) { | |
| 516 GURL u(*url); | |
| 517 if (TabContents::TypeForURL(&u) == type()) { | |
| 518 *url = u; | |
| 519 return true; | |
| 520 } | |
| 521 return false; | |
| 522 } | |
| 523 | |
| 524 void TabContents::ToolbarSizeChanged(bool is_animating) { | 405 void TabContents::ToolbarSizeChanged(bool is_animating) { |
| 525 TabContentsDelegate* d = delegate(); | 406 TabContentsDelegate* d = delegate(); |
| 526 if (d) | 407 if (d) |
| 527 d->ToolbarSizeChanged(this, is_animating); | 408 d->ToolbarSizeChanged(this, is_animating); |
| 528 } | 409 } |
| 529 | 410 |
| 411 void TabContents::OnStartDownload(DownloadItem* download) { |
| 412 DCHECK(download); |
| 413 TabContents* tab_contents = this; |
| 414 |
| 415 // Download in a constrained popup is shown in the tab that opened it. |
| 416 TabContents* constraining_tab = delegate()->GetConstrainingContents(this); |
| 417 if (constraining_tab) |
| 418 tab_contents = constraining_tab; |
| 419 |
| 420 // GetDownloadShelfView creates the download shelf if it was not yet created. |
| 421 tab_contents->GetDownloadShelfView()->AddDownload(download); |
| 422 tab_contents->SetDownloadShelfVisible(true); |
| 423 |
| 424 // This animation will delete itself when it finishes, or if we become hidden |
| 425 // or destroyed. |
| 426 if (IsWindowVisible(GetContainerHWND())) { // For minimized windows, unit |
| 427 // tests, etc. |
| 428 new DownloadStartedAnimation(tab_contents); |
| 429 } |
| 430 } |
| 431 |
| 530 DownloadShelfView* TabContents::GetDownloadShelfView() { | 432 DownloadShelfView* TabContents::GetDownloadShelfView() { |
| 531 if (!download_shelf_view_.get()) { | 433 if (!download_shelf_view_.get()) { |
| 532 download_shelf_view_.reset(new DownloadShelfView(this)); | 434 download_shelf_view_.reset(new DownloadShelfView(this)); |
| 533 // The TabContents owns the download-shelf. | 435 // The TabContents owns the download-shelf. |
| 534 download_shelf_view_->SetParentOwned(false); | 436 download_shelf_view_->SetParentOwned(false); |
| 535 } | 437 } |
| 536 return download_shelf_view_.get(); | 438 return download_shelf_view_.get(); |
| 537 } | 439 } |
| 538 | 440 |
| 539 void TabContents::MigrateShelfViewFrom(TabContents* tab_contents) { | 441 void TabContents::MigrateShelfViewFrom(TabContents* tab_contents) { |
| 540 download_shelf_view_.reset(tab_contents->GetDownloadShelfView()); | 442 download_shelf_view_.reset(tab_contents->GetDownloadShelfView()); |
| 541 download_shelf_view_->ChangeTabContents(tab_contents, this); | 443 download_shelf_view_->ChangeTabContents(tab_contents, this); |
| 542 tab_contents->ReleaseDownloadShelfView(); | 444 tab_contents->ReleaseDownloadShelfView(); |
| 543 } | 445 } |
| 544 | 446 |
| 447 void TabContents::AddNewContents(ConstrainedWindow* window, |
| 448 TabContents* new_contents, |
| 449 WindowOpenDisposition disposition, |
| 450 const gfx::Rect& initial_pos, |
| 451 bool user_gesture) { |
| 452 AddNewContents(new_contents, disposition, initial_pos, user_gesture); |
| 453 } |
| 454 |
| 455 void TabContents::OpenURL(ConstrainedWindow* window, |
| 456 const GURL& url, |
| 457 WindowOpenDisposition disposition, |
| 458 PageTransition::Type transition) { |
| 459 OpenURL(url, disposition, transition); |
| 460 } |
| 461 |
| 462 void TabContents::WillClose(ConstrainedWindow* window) { |
| 463 ConstrainedWindowList::iterator it = |
| 464 find(child_windows_.begin(), child_windows_.end(), window); |
| 465 if (it != child_windows_.end()) |
| 466 child_windows_.erase(it); |
| 467 |
| 468 if (::IsWindow(GetContainerHWND())) { |
| 469 CRect client_rect; |
| 470 GetClientRect(GetContainerHWND(), &client_rect); |
| 471 RepositionSupressedPopupsToFit( |
| 472 gfx::Size(client_rect.Width(), client_rect.Height())); |
| 473 } |
| 474 } |
| 475 |
| 476 void TabContents::DetachContents(ConstrainedWindow* window, |
| 477 TabContents* contents, |
| 478 const gfx::Rect& contents_bounds, |
| 479 const gfx::Point& mouse_pt, |
| 480 int frame_component) { |
| 481 WillClose(window); |
| 482 if (delegate_) { |
| 483 delegate_->StartDraggingDetachedContents( |
| 484 this, contents, contents_bounds, mouse_pt, frame_component); |
| 485 } |
| 486 } |
| 487 |
| 488 void TabContents::DidMoveOrResize(ConstrainedWindow* window) { |
| 489 UpdateWindow(GetContainerHWND()); |
| 490 } |
| 491 |
| 545 // static | 492 // static |
| 546 void TabContents::MigrateShelfView(TabContents* from, TabContents* to) { | 493 void TabContents::MigrateShelfView(TabContents* from, TabContents* to) { |
| 547 bool was_shelf_visible = from->IsDownloadShelfVisible(); | 494 bool was_shelf_visible = from->IsDownloadShelfVisible(); |
| 548 if (was_shelf_visible) | 495 if (was_shelf_visible) |
| 549 to->MigrateShelfViewFrom(from); | 496 to->MigrateShelfViewFrom(from); |
| 550 to->SetDownloadShelfVisible(was_shelf_visible); | 497 to->SetDownloadShelfVisible(was_shelf_visible); |
| 551 } | 498 } |
| 552 | 499 |
| 553 // static | 500 void TabContents::SetIsLoading(bool is_loading, |
| 554 void TabContents::RegisterUserPrefs(PrefService* prefs) { | 501 LoadNotificationDetails* details) { |
| 555 prefs->RegisterBooleanPref(prefs::kBlockPopups, false); | 502 if (is_loading == is_loading_) |
| 503 return; |
| 504 |
| 505 is_loading_ = is_loading; |
| 506 waiting_for_response_ = is_loading; |
| 507 |
| 508 // Suppress notifications for this TabContents if we are not active. |
| 509 if (!is_active_) |
| 510 return; |
| 511 |
| 512 if (delegate_) |
| 513 delegate_->LoadingStateChanged(this); |
| 514 |
| 515 NotificationService::current()-> |
| 516 Notify((is_loading ? NOTIFY_LOAD_START : NOTIFY_LOAD_STOP), |
| 517 Source<NavigationController>(this->controller()), |
| 518 details ? Details<LoadNotificationDetails>(details) : |
| 519 NotificationService::NoDetails()); |
| 556 } | 520 } |
| 557 | 521 |
| 522 void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) { |
| 523 // TODO(erg): There's no way to detect whether scroll bars are |
| 524 // visible, so for beta, we're just going to assume that the |
| 525 // vertical scroll bar is visible, and not care about covering up |
| 526 // the horizontal scroll bar. Fixing this is half of |
| 527 // http://b/1118139. |
| 528 gfx::Point anchor_position( |
| 529 new_size.width() - |
| 530 ChromeViews::NativeScrollBar::GetVerticalScrollBarWidth(), |
| 531 new_size.height()); |
| 532 int window_count = static_cast<int>(child_windows_.size()); |
| 533 for (int i = window_count - 1; i >= 0; --i) { |
| 534 ConstrainedWindow* window = child_windows_.at(i); |
| 535 if (window->IsSuppressedConstrainedWindow()) |
| 536 window->RepositionConstrainedWindowTo(anchor_position); |
| 537 } |
| 538 } |
| 539 |
| 540 void TabContents::ReleaseDownloadShelfView() { |
| 541 download_shelf_view_.release(); |
| 542 } |
| OLD | NEW |