1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/prerender/prerender_handle.h" 6 7 #include <algorithm> 8 9 #include "base/logging.h" 10 #include "chrome/browser/prerender/prerender_contents.h" 11 #include "content/public/browser/web_contents.h" 12 13 namespace prerender { 14 15 PrerenderHandle::Observer::Observer() { 16 } 17 18 PrerenderHandle::Observer::~Observer() { 19 } 20 21 PrerenderHandle::~PrerenderHandle() { 22 if (prerender_data_.get()) { 23 prerender_data_->contents()->RemoveObserver(this); 24 } 25 } 26 27 void PrerenderHandle::SetObserver(Observer* observer) { 28 DCHECK_NE(static_cast<Observer*>(NULL), observer); 29 observer_ = observer; 30 } 31 32 void PrerenderHandle::OnNavigateAway() { 33 DCHECK(CalledOnValidThread()); 34 if (prerender_data_.get()) 35 prerender_data_->OnHandleNavigatedAway(this); 36 } 37 38 void PrerenderHandle::OnCancel() { 39 DCHECK(CalledOnValidThread()); 40 if (prerender_data_.get()) 41 prerender_data_->OnHandleCanceled(this); 42 } 43 44 bool PrerenderHandle::IsPrerendering() const { 45 DCHECK(CalledOnValidThread()); 46 return prerender_data_.get() != NULL; 47 } 48 49 bool PrerenderHandle::IsFinishedLoading() const { 50 DCHECK(CalledOnValidThread()); 51 if (!prerender_data_.get()) 52 return false; 53 return prerender_data_->contents()->has_finished_loading(); 54 } 55 56 PrerenderContents* PrerenderHandle::contents() const { 57 DCHECK(CalledOnValidThread()); 58 return prerender_data_ ? prerender_data_->contents() : NULL; 59 } 60 61 bool PrerenderHandle::Matches( 62 const GURL& url, 63 const content::SessionStorageNamespace* session_storage_namespace) const { 64 DCHECK(CalledOnValidThread()); 65 if (!prerender_data_.get()) 66 return false; 67 return prerender_data_->contents()->Matches(url, session_storage_namespace); 68 } 69 70 PrerenderHandle::PrerenderHandle( 71 PrerenderManager::PrerenderData* prerender_data) 72 : observer_(NULL), 73 weak_ptr_factory_(this) { 74 if (prerender_data) { 75 prerender_data_ = prerender_data->AsWeakPtr(); 76 prerender_data->OnHandleCreated(this); 77 } 78 } 79 80 void PrerenderHandle::AdoptPrerenderDataFrom(PrerenderHandle* other_handle) { 81 DCHECK_EQ(static_cast<PrerenderManager::PrerenderData*>(NULL), 82 prerender_data_.get()); 83 if (other_handle->prerender_data_.get() && 84 other_handle->prerender_data_->contents()) { 85 other_handle->prerender_data_->contents()->RemoveObserver(other_handle); 86 } 87 88 prerender_data_ = other_handle->prerender_data_; 89 other_handle->prerender_data_.reset(); 90 91 if (prerender_data_.get()) { 92 DCHECK_NE(static_cast<PrerenderContents*>(NULL), 93 prerender_data_->contents()); 94 prerender_data_->contents()->AddObserver(this); 95 // We are joining a prerender that has already started so we fire off an 96 // extra start event at ourselves. 97 OnPrerenderStart(prerender_data_->contents()); 98 } 99 } 100 101 void PrerenderHandle::OnPrerenderStart(PrerenderContents* prerender_contents) { 102 DCHECK(CalledOnValidThread()); 103 DCHECK(prerender_data_.get()); 104 DCHECK_EQ(prerender_data_->contents(), prerender_contents); 105 if (observer_) 106 observer_->OnPrerenderStart(this); 107 } 108 109 void PrerenderHandle::OnPrerenderStopLoading( 110 PrerenderContents* prerender_contents) { 111 DCHECK(CalledOnValidThread()); 112 DCHECK(prerender_data_.get()); 113 DCHECK_EQ(prerender_data_->contents(), prerender_contents); 114 if (observer_) 115 observer_->OnPrerenderStopLoading(this); 116 } 117 118 void PrerenderHandle::OnPrerenderStop(PrerenderContents* prerender_contents) { 119 DCHECK(CalledOnValidThread()); 120 if (observer_) 121 observer_->OnPrerenderStop(this); 122 } 123 124 void PrerenderHandle::OnPrerenderCreatedMatchCompleteReplacement( 125 PrerenderContents* contents, PrerenderContents* replacement) { 126 DCHECK(CalledOnValidThread()); 127 128 // This should occur in the middle of the surgery on the PrerenderData, and 129 // so we expect to not have our new contents in our PrerenderData yet. The 130 // switch occurs in 131 // PrerenderManager::PrerenderData::MakeIntoMatchCompleteReplacement, so 132 // this method only needs to switch observing. 133 134 contents->RemoveObserver(this); 135 replacement->AddObserver(this); 136 if (observer_) 137 observer_->OnPrerenderCreatedMatchCompleteReplacement(this); 138 } 139 140 bool PrerenderHandle::RepresentingSamePrerenderAs( 141 PrerenderHandle* other) const { 142 return other && other->prerender_data_.get() && prerender_data_.get() 143 && prerender_data_.get() == other->prerender_data_.get(); 144 } 145 146 content::SessionStorageNamespace* 147 PrerenderHandle::GetSessionStorageNamespace() const { 148 if (!prerender_data_.get()) 149 return NULL; 150 return prerender_data_->contents()->GetSessionStorageNamespace(); 151 } 152 153 int PrerenderHandle::GetChildId() const { 154 if (!prerender_data_.get()) 155 return -1; 156 return prerender_data_->contents()->child_id(); 157 } 158 159 } // namespace prerender 160