instant_service.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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/search/instant_service.h" 6 7#include "base/strings/string_number_conversions.h" 8#include "chrome/browser/history/history_notifications.h" 9#include "chrome/browser/profiles/profile.h" 10#include "chrome/browser/search/instant_io_context.h" 11#include "chrome/browser/search/instant_service_factory.h" 12#include "chrome/browser/search/local_ntp_source.h" 13#include "chrome/browser/search/most_visited_iframe_source.h" 14#include "chrome/browser/search/suggestion_iframe_source.h" 15#include "chrome/browser/ui/webui/favicon_source.h" 16#include "chrome/browser/ui/webui/ntp/thumbnail_source.h" 17#include "chrome/browser/ui/webui/theme_source.h" 18#include "chrome/common/chrome_notification_types.h" 19#include "content/public/browser/browser_thread.h" 20#include "content/public/browser/notification_service.h" 21#include "content/public/browser/notification_types.h" 22#include "content/public/browser/render_process_host.h" 23#include "content/public/browser/url_data_source.h" 24#include "googleurl/src/gurl.h" 25#include "net/url_request/url_request.h" 26 27using content::BrowserThread; 28 29InstantService::InstantService(Profile* profile) 30 : profile_(profile), 31 most_visited_item_cache_(kMaxInstantMostVisitedItemCacheSize) { 32 // Stub for unit tests. 33 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) 34 return; 35 36 registrar_.Add(this, 37 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 38 content::NotificationService::AllSources()); 39 40 instant_io_context_ = new InstantIOContext(); 41 42 if (profile_ && profile_->GetResourceContext()) { 43 BrowserThread::PostTask( 44 BrowserThread::IO, FROM_HERE, 45 base::Bind(&InstantIOContext::SetUserDataOnIO, 46 profile->GetResourceContext(), instant_io_context_)); 47 } 48 49 // Set up the data sources that Instant uses on the NTP. 50#if defined(ENABLE_THEMES) 51 content::URLDataSource::Add(profile, new ThemeSource(profile)); 52#endif 53 content::URLDataSource::Add(profile, new ThumbnailSource(profile)); 54 content::URLDataSource::Add(profile, new FaviconSource( 55 profile, FaviconSource::FAVICON)); 56 content::URLDataSource::Add(profile, new LocalNtpSource()); 57 content::URLDataSource::Add(profile, new SuggestionIframeSource()); 58 content::URLDataSource::Add(profile, new MostVisitedIframeSource()); 59} 60 61InstantService::~InstantService() { 62} 63 64// static 65const std::string InstantService::MaybeTranslateInstantPathOnUI( 66 Profile* profile, const std::string& path) { 67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 68 InstantService* instant_service = 69 InstantServiceFactory::GetForProfile(profile); 70 if (!instant_service) 71 return path; 72 73 InstantRestrictedID restricted_id = 0; 74 DCHECK_EQ(sizeof(InstantRestrictedID), sizeof(int)); 75 if (base::StringToInt(path, &restricted_id)) { 76 InstantMostVisitedItem item; 77 if (instant_service->GetMostVisitedItemForID(restricted_id, &item)) 78 return item.url.spec(); 79 } 80 return path; 81} 82 83const std::string InstantService::MaybeTranslateInstantPathOnIO( 84 const net::URLRequest* request, const std::string& path) { 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 86 87 InstantRestrictedID restricted_id = 0; 88 DCHECK_EQ(sizeof(InstantRestrictedID), sizeof(int)); 89 if (base::StringToInt(path, &restricted_id)) { 90 GURL url; 91 if (InstantIOContext::GetURLForMostVisitedItemID(request, 92 restricted_id, 93 &url)) { 94 return url.spec(); 95 } 96 } 97 return path; 98} 99 100// static 101bool InstantService::IsInstantPath(const GURL& url) { 102 // Strip leading slash. 103 std::string path = url.path().substr(1); 104 105 // Check that path is of Most Visited item ID form. 106 InstantRestrictedID dummy = 0; 107 return base::StringToInt(path, &dummy); 108} 109 110void InstantService::AddInstantProcess(int process_id) { 111 process_ids_.insert(process_id); 112 113 if (instant_io_context_) { 114 BrowserThread::PostTask( 115 BrowserThread::IO, FROM_HERE, 116 base::Bind(&InstantIOContext::AddInstantProcessOnIO, 117 instant_io_context_, process_id)); 118 } 119} 120 121bool InstantService::IsInstantProcess(int process_id) const { 122 return process_ids_.find(process_id) != process_ids_.end(); 123} 124 125void InstantService::AddMostVisitedItems( 126 const std::vector<InstantMostVisitedItem>& items) { 127 most_visited_item_cache_.AddItems(items); 128 129 // Post task to the IO thread to copy the data. 130 if (instant_io_context_) { 131 std::vector<InstantMostVisitedItemIDPair> items; 132 most_visited_item_cache_.GetCurrentItems(&items); 133 BrowserThread::PostTask( 134 BrowserThread::IO, FROM_HERE, 135 base::Bind(&InstantIOContext::AddMostVisitedItemsOnIO, 136 instant_io_context_, 137 items)); 138 } 139} 140 141void InstantService::GetCurrentMostVisitedItems( 142 std::vector<InstantMostVisitedItemIDPair>* items) const { 143 most_visited_item_cache_.GetCurrentItems(items); 144} 145 146bool InstantService::GetMostVisitedItemForID( 147 InstantRestrictedID most_visited_item_id, 148 InstantMostVisitedItem* item) const { 149 return most_visited_item_cache_.GetItemWithRestrictedID( 150 most_visited_item_id, item); 151} 152 153void InstantService::Shutdown() { 154 process_ids_.clear(); 155 156 if (instant_io_context_) { 157 BrowserThread::PostTask( 158 BrowserThread::IO, FROM_HERE, 159 base::Bind(&InstantIOContext::ClearInstantProcessesOnIO, 160 instant_io_context_)); 161 } 162 instant_io_context_ = NULL; 163} 164 165void InstantService::Observe(int type, 166 const content::NotificationSource& source, 167 const content::NotificationDetails& details) { 168 switch (type) { 169 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { 170 int process_id = 171 content::Source<content::RenderProcessHost>(source)->GetID(); 172 process_ids_.erase(process_id); 173 174 if (instant_io_context_) { 175 BrowserThread::PostTask( 176 BrowserThread::IO, FROM_HERE, 177 base::Bind(&InstantIOContext::RemoveInstantProcessOnIO, 178 instant_io_context_, process_id)); 179 } 180 break; 181 } 182 default: 183 NOTREACHED() << "Unexpected notification type in InstantService."; 184 } 185} 186