1 // Copyright 2013 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/ui/search/instant_page.h" 6 7 #include "chrome/browser/profiles/profile.h" 8 #include "chrome/browser/search/search.h" 9 #include "chrome/browser/ui/search/search_model.h" 10 #include "chrome/browser/ui/search/search_tab_helper.h" 11 #include "chrome/common/render_messages.h" 12 #include "chrome/common/url_constants.h" 13 #include "content/public/browser/navigation_controller.h" 14 #include "content/public/browser/navigation_details.h" 15 #include "content/public/browser/navigation_entry.h" 16 #include "content/public/browser/notification_service.h" 17 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/web_contents.h" 19 #include "content/public/common/frame_navigate_params.h" 20 21 InstantPage::Delegate::~Delegate() { 22 } 23 24 InstantPage::~InstantPage() { 25 if (contents()) 26 SearchTabHelper::FromWebContents(contents())->model()->RemoveObserver(this); 27 } 28 29 bool InstantPage::supports_instant() const { 30 return contents() ? 31 SearchTabHelper::FromWebContents(contents())->SupportsInstant() : false; 32 } 33 34 const std::string& InstantPage::instant_url() const { 35 return instant_url_; 36 } 37 38 bool InstantPage::IsLocal() const { 39 return contents() && 40 contents()->GetURL() == GURL(chrome::kChromeSearchLocalNtpUrl); 41 } 42 43 InstantPage::InstantPage(Delegate* delegate, const std::string& instant_url, 44 Profile* profile, bool is_incognito) 45 : profile_(profile), 46 delegate_(delegate), 47 ipc_sender_(InstantIPCSender::Create(is_incognito)), 48 instant_url_(instant_url), 49 is_incognito_(is_incognito) { 50 } 51 52 void InstantPage::SetContents(content::WebContents* web_contents) { 53 ClearContents(); 54 55 if (!web_contents) 56 return; 57 58 sender()->SetContents(web_contents); 59 Observe(web_contents); 60 SearchModel* model = SearchTabHelper::FromWebContents(contents())->model(); 61 model->AddObserver(this); 62 63 // Already know whether the page supports instant. 64 if (model->instant_support() != INSTANT_SUPPORT_UNKNOWN) 65 InstantSupportDetermined(model->instant_support() == INSTANT_SUPPORT_YES); 66 } 67 68 bool InstantPage::ShouldProcessAboutToNavigateMainFrame() { 69 return false; 70 } 71 72 void InstantPage::DidCommitProvisionalLoadForFrame( 73 int64 /* frame_id */, 74 const base::string16& frame_unique_name, 75 bool is_main_frame, 76 const GURL& url, 77 content::PageTransition /* transition_type */, 78 content::RenderViewHost* /* render_view_host */) { 79 if (is_main_frame && ShouldProcessAboutToNavigateMainFrame()) 80 delegate_->InstantPageAboutToNavigateMainFrame(contents(), url); 81 } 82 83 void InstantPage::DidNavigateMainFrame( 84 const content::LoadCommittedDetails& details, 85 const content::FrameNavigateParams& /* params */) { 86 // A 204 can be sent by the search provider as a lightweight signal 87 // to fall back to the local page, and we obviously want to fall back 88 // if we get any response code that indicates an error. 89 if (details.http_status_code == 204 || details.http_status_code >= 400) 90 delegate_->InstantPageLoadFailed(contents()); 91 } 92 93 void InstantPage::DidFailProvisionalLoad( 94 int64 /* frame_id */, 95 const base::string16& frame_unique_name, 96 bool is_main_frame, 97 const GURL& /* validated_url */, 98 int /* error_code */, 99 const base::string16& /* error_description */, 100 content::RenderViewHost* /* render_view_host */) { 101 if (is_main_frame) 102 delegate_->InstantPageLoadFailed(contents()); 103 } 104 105 void InstantPage::ModelChanged(const SearchModel::State& old_state, 106 const SearchModel::State& new_state) { 107 if (old_state.instant_support != new_state.instant_support) 108 InstantSupportDetermined(new_state.instant_support == INSTANT_SUPPORT_YES); 109 } 110 111 void InstantPage::InstantSupportDetermined(bool supports_instant) { 112 delegate_->InstantSupportDetermined(contents(), supports_instant); 113 114 // If the page doesn't support Instant, stop listening to it. 115 if (!supports_instant) 116 ClearContents(); 117 } 118 119 void InstantPage::ClearContents() { 120 if (contents()) 121 SearchTabHelper::FromWebContents(contents())->model()->RemoveObserver(this); 122 123 sender()->SetContents(NULL); 124 Observe(NULL); 125 } 126