1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifndef CHROME_BROWSER_UI_FAST_UNLOAD_CONTROLLER_H_ 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define CHROME_BROWSER_UI_FAST_UNLOAD_CONTROLLER_H_ 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <set> 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/callback.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/memory/scoped_ptr.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/memory/weak_ptr.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_piece.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/notification_observer.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/browser/notification_registrar.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass Browser; 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass TabStripModel; 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace content { 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass NotificationSource; 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class NotificationDetails; 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass WebContents; 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace chrome { 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// FastUnloadController manages closing tabs and windows -- especially in 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// regards to beforeunload handlers (have proceed/cancel dialogs) and 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// unload handlers (have no user interaction). 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Typical flow of closing a tab: 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 1. Browser calls CanCloseContents(). 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// If true, browser calls contents::CloseWebContents(). 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 2. WebContents notifies us via its delegate and BeforeUnloadFired() 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that the beforeunload handler was run. If the user allowed the 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// close to continue, we detached the tab and hold onto it while the 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// close finishes. 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Typical flow of closing a window: 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 1. BrowserView::CanClose() calls TabsNeedBeforeUnloadFired(). 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// If beforeunload/unload handlers need to run, FastUnloadController returns 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// true and calls ProcessPendingTabs() (private method). 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 2. For each tab with a beforeunload/unload handler, ProcessPendingTabs() 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// calls |CoreTabHelper::OnCloseStarted()| 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// and |web_contents->GetRenderViewHost()->FirePageBeforeUnload()|. 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 3. If the user allowed the close to continue, we detach all the tabs with 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// unload handlers, remove them from the tab strip, and finish closing 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the tabs in the background. 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 4. The browser gets notified that the tab strip is empty and calls 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// CloseFrame where the empty tab strip causes the window to hide. 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Once the detached tabs finish, the browser calls CloseFrame again and 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the window is finally closed. 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass FastUnloadController : public content::NotificationObserver, 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public TabStripModelObserver { 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch explicit FastUnloadController(Browser* browser); 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~FastUnloadController(); 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Returns true if |contents| can be cleanly closed. When |browser_| is being 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // closed, this function will return false to indicate |contents| should not 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // be cleanly closed, since the fast shutdown path will just kill its 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // renderer. 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool CanCloseContents(content::WebContents* contents); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Returns true if we need to run unload events for the |contents|. 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static bool ShouldRunUnloadEventsHelper(content::WebContents* contents); 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Helper function to run beforeunload listeners on a WebContents. 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Returns true if |contents| beforeunload listeners were invoked. 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static bool RunUnloadEventsHelper(content::WebContents* contents); 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Called when a BeforeUnload handler is fired for |contents|. |proceed| 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // indicates the user's response to the Y/N BeforeUnload handler dialog. If 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // this parameter is false, any pending attempt to close the whole browser 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // will be canceled. Returns true if Unload handlers should be fired. When the 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // |browser_| is being closed, Unload handlers for any particular WebContents 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // will not be run until every WebContents being closed has a chance to run 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // its BeforeUnloadHandler. 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool BeforeUnloadFired(content::WebContents* contents, bool proceed); 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool is_attempting_to_close_browser() const { 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return is_attempting_to_close_browser_; 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Called in response to a request to close |browser_|'s window. Returns true 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // when there are no remaining beforeunload handlers to be run. 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool ShouldCloseWindow(); 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Begins the process of confirming whether the associated browser can be 923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // closed. 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool CallBeforeUnloadHandlers( 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::Callback<void(bool)>& on_close_confirmed); 953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Clears the results of any beforeunload confirmation dialogs triggered by a 973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // CallBeforeUnloadHandlers call. 983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void ResetBeforeUnloadHandlers(); 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Returns true if |browser_| has any tabs that have BeforeUnload handlers 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // that have not been fired. This method is non-const because it builds a list 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // of tabs that need their BeforeUnloadHandlers fired. 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(beng): This seems like it could be private but it is used by 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // AreAllBrowsersCloseable() in application_lifetime.cc. It seems 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // very similar to ShouldCloseWindow() and some consolidation 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // could be pursued. 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool TabsNeedBeforeUnloadFired(); 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Returns true if all tabs' beforeunload/unload events have fired. 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool HasCompletedUnloadProcessing() const; 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Clears all the state associated with processing tabs' beforeunload/unload 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // events since the user cancelled closing the window. 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void CancelWindowClose(); 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Overridden from content::NotificationObserver: 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void Observe(int type, 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const content::NotificationSource& source, 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const content::NotificationDetails& details) OVERRIDE; 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Overridden from TabStripModelObserver: 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void TabInsertedAt(content::WebContents* contents, 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int index, 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool foreground) OVERRIDE; 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void TabDetachedAt(content::WebContents* contents, 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int index) OVERRIDE; 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void TabReplacedAt(TabStripModel* tab_strip_model, 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::WebContents* old_contents, 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::WebContents* new_contents, 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int index) OVERRIDE; 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void TabStripEmpty() OVERRIDE; 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void TabAttachedImpl(content::WebContents* contents); 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void TabDetachedImpl(content::WebContents* contents); 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Detach |contents| and wait for it to finish closing. 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // The close must be inititiated outside of this method. 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Returns true if it succeeds. 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool DetachWebContents(content::WebContents* contents); 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Processes the next tab that needs it's beforeunload/unload event fired. 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void ProcessPendingTabs(); 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Cleans up state appropriately when we are trying to close the 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // browser or close a tab in the background. We also use this in the 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // cases where a tab crashes or hangs even if the 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // beforeunload/unload haven't successfully fired. 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void ClearUnloadState(content::WebContents* contents); 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Helper for |ClearUnloadState| to unwind stack before proceeding. 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void PostTaskForProcessPendingTabs(); 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Log a step of the unload processing. 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void LogUnloadStep(const base::StringPiece& step_name, 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::WebContents* contents) const; 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool is_calling_before_unload_handlers() { 1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return !on_close_confirmed_.is_null(); 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Browser* browser_; 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationRegistrar registrar_; 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch typedef std::set<content::WebContents*> WebContentsSet; 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Tracks tabs that need their beforeunload event started. 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only gets populated when we try to close the browser. 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebContentsSet tabs_needing_before_unload_; 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Tracks the tab that needs its beforeunload event result. 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only gets populated when we try to close the browser. 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::WebContents* tab_needing_before_unload_ack_; 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Tracks tabs that need their unload event started. 177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only gets populated when we try to close the browser. 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebContentsSet tabs_needing_unload_; 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Tracks tabs that need to finish running their unload event. 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Populated both when closing individual tabs and when closing the browser. 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebContentsSet tabs_needing_unload_ack_; 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Whether we are processing the beforeunload and unload events of each tab 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // in preparation for closing the browser. FastUnloadController owns this 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // state rather than Browser because unload handlers are the only reason that 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // a Browser window isn't just immediately closed. 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool is_attempting_to_close_browser_; 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // A callback to call to report whether the user chose to close all tabs of 1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // |browser_| that have beforeunload event handlers. This is set only if we 1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // are currently confirming that the browser is closable. 1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Callback<void(bool)> on_close_confirmed_; 1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Manage tabs with beforeunload/unload handlers that close detached. 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch class DetachedWebContentsDelegate; 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<DetachedWebContentsDelegate> detached_delegate_; 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtrFactory<FastUnloadController> weak_factory_; 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DISALLOW_COPY_AND_ASSIGN(FastUnloadController); 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace chrome 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif // CHROME_BROWSER_UI_FAST_UNLOAD_CONTROLLER_H_ 207