15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/in_memory_history_backend.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_notifications.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/history/core/browser/in_memory_database.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/history/core/browser/url_database.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryHistoryBackend::InMemoryHistoryBackend() 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : profile_(NULL) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryHistoryBackend::~InMemoryHistoryBackend() {} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool InMemoryHistoryBackend::Init(const base::FilePath& history_filename) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(new InMemoryDatabase); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->InitFromDisk(history_filename); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryHistoryBackend::AttachToHistoryService(Profile* profile) { 36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_ = profile; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(evanm): this is currently necessitated by generate_profile, which 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // runs without a browser process. generate_profile should really create 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a browser process, at which point this check can then be nuked. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_browser_process) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register for the notifications we care about. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only want notifications for the associated profile. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile> source(profile_); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source); 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, source); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source); 550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) registrar_.Add( 560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, source); 570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) registrar_.Add( 580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, source); 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid InMemoryHistoryBackend::DeleteAllSearchTermsForKeyword( 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch KeywordID keyword_id) { 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // For simplicity, this will not remove the corresponding URLRows, but 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // this is okay, as the main database does not do so either. 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch db_->DeleteAllSearchTermsForKeyword(keyword_id); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryHistoryBackend::Observe( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case chrome::NOTIFICATION_HISTORY_URL_VISITED: 740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch OnURLVisitedOrModified(content::Details<URLVisitedDetails>(details)->row); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnKeywordSearchTermUpdated( 780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch *content::Details<KeywordSearchUpdatedDetails>(details).ptr()); 790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED: 810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) OnKeywordSearchTermDeleted( 820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch *content::Details<KeywordSearchDeletedDetails>(details).ptr()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED: { 850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const URLsModifiedDetails* modified_details = 860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch content::Details<URLsModifiedDetails>(details).ptr(); 870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch URLRows::const_iterator it; 880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (it = modified_details->changed_urls.begin(); 890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != modified_details->changed_urls.end(); ++it) { 900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch OnURLVisitedOrModified(*it); 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_HISTORY_URLS_DELETED: 950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch OnURLsDeleted(*content::Details<URLsDeletedDetails>(details).ptr()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For simplicity, the unit tests send us all notifications, even when 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we haven't registered for them, so don't assert here. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid InMemoryHistoryBackend::OnURLVisitedOrModified(const URLRow& url_row) { 105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(db_); 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(url_row.id()); 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (url_row.typed_count() || db_->GetKeywordSearchTermRow(url_row.id(), NULL)) 1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->InsertOrUpdateURLRowByID(url_row); 1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch else 1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->DeleteURLRow(url_row.id()); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryHistoryBackend::OnURLsDeleted(const URLsDeletedDetails& details) { 114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(db_); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (details.all_history) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When all history is deleted, the individual URLs won't be listed. Just 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // create a new database to quickly clear everything out. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(new InMemoryDatabase); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->InitFromScratch()) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete all matching URLs in our database. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator row = details.rows.begin(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row != details.rows.end(); ++row) { 1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // This will also delete the corresponding keyword search term. 1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Ignore errors, as we typically only cache a subset of URLRows. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteURLRow(row->id()); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryHistoryBackend::OnKeywordSearchTermUpdated( 1350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const KeywordSearchUpdatedDetails& details) { 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(details.url_row.id()); 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->InsertOrUpdateURLRowByID(details.url_row); 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->SetKeywordSearchTermsForURL( 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch details.url_row.id(), details.keyword_id, details.term); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void InMemoryHistoryBackend::OnKeywordSearchTermDeleted( 1430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const KeywordSearchDeletedDetails& details) { 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // For simplicity, this will not remove the corresponding URLRow, but this is 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // okay, as the main database does not do so either. 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->DeleteKeywordSearchTermForURL(details.url_row_id); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 150