template_url_table_model.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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/ui/search_engines/template_url_table_model.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/favicon/favicon_types.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/cancelable_task_tracker.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/table_model_observer.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/favicon_size.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Group IDs used by TemplateURLTableModel. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMainGroupID = 0; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kOtherGroupID = 1; 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const int kExtensionGroupID = 2; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ModelEntry ---------------------------------------------------- 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ModelEntry wraps a TemplateURL as returned from the TemplateURL. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ModelEntry also tracks state information about the URL. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Icon used while loading, or if a specific favicon can't be found. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static gfx::ImageSkia* default_icon = NULL; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ModelEntry { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelEntry(TemplateURLTableModel* model, TemplateURL* template_url) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : template_url_(template_url), 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_(NOT_LOADED), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_(model) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!default_icon) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_icon = ResourceBundle::GetSharedInstance(). 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetImageSkiaNamed(IDR_DEFAULT_FAVICON); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url() { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return template_url_; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia GetIcon() { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (load_state_ == NOT_LOADED) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadFavicon(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_.isNull()) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return favicon_; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *default_icon; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Resets internal status so that the next time the icon is asked for its 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fetched again. This should be invoked if the url is modified. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ResetIcon() { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ = NOT_LOADED; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ = gfx::ImageSkia(); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // State of the favicon. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum LoadState { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOT_LOADED, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOADING, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOADED 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void LoadFavicon() { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ = LOADED; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->template_url_service()->profile(), Profile::EXPLICIT_ACCESS); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_service) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL favicon_url = template_url()->favicon_url(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_url.is_valid()) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The favicon url isn't always set. Guess at one here. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (template_url_->url_ref().IsValid()) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url(template_url_->url()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.is_valid()) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_url = TemplateURL::GenerateFaviconURL(url); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_url.is_valid()) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ = LOADING; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_service->GetFaviconImage( 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) favicon_url, chrome::FAVICON, gfx::kFaviconSize, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ModelEntry::OnFaviconDataAvailable, 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this)), 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &tracker_); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void OnFaviconDataAvailable(const chrome::FaviconImageResult& image_result) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ = LOADED; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_result.image.IsEmpty()) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ = image_result.image.AsImageSkia(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->FaviconAvailable(this); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url_; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia favicon_; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadState load_state_; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLTableModel* model_; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker tracker_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ModelEntry); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TemplateURLTableModel ----------------------------------------- 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLTableModel::TemplateURLTableModel( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLService* template_url_service) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : observer_(NULL), 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_(template_url_service) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(template_url_service); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->Load(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reload(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLTableModel::~TemplateURLTableModel() { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&entries_); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_.clear(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::Reload() { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&entries_); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_.clear(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLService::TemplateURLVector urls = 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->GetTemplateURLs(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<ModelEntry*> default_entries, other_entries, extension_entries; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keywords that can be made the default first. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (TemplateURLService::TemplateURLVector::iterator i = urls.begin(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != urls.end(); ++i) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url = *i; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: we don't use ShowInDefaultList here to avoid items bouncing around 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the lists while editing. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (template_url->show_in_default_list()) 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default_entries.push_back(new ModelEntry(this, template_url)); 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) else if (template_url->IsExtensionKeyword()) 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_entries.push_back(new ModelEntry(this, template_url)); 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) else 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) other_entries.push_back(new ModelEntry(this, template_url)); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_search_engine_index_ = static_cast<int>(default_entries.size()); 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_other_engine_index_ = last_search_engine_index_ + 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<int>(other_entries.size()); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entries_.insert(entries_.end(), 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default_entries.begin(), 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default_entries.end()); 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entries_.insert(entries_.end(), 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) other_entries.begin(), 172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) other_entries.end()); 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entries_.insert(entries_.end(), 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_entries.begin(), 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_entries.end()); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer_) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->OnModelChanged(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::RowCount() { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(entries_.size()); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 TemplateURLTableModel::GetText(int row, int col_id) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(row >= 0 && row < RowCount()); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* url = entries_[row]->template_url(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (col_id == IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 url_short_name = url->short_name(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(xji): Consider adding a special case if the short name is a URL, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since those should always be displayed LTR. Please refer to 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/6726 for more information. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::AdjustStringForLocaleDirection(&url_short_name); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (template_url_service_->GetDefaultSearchProvider() == url) ? 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16(IDS_SEARCH_ENGINES_EDITOR_DEFAULT_ENGINE, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_short_name) : url_short_name; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN, col_id); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keyword should be domain name. Force it to have LTR directionality. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::i18n::GetDisplayStringInLTRDirectionality(url->keyword()); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkia TemplateURLTableModel::GetIcon(int row) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(row >= 0 && row < RowCount()); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entries_[row]->GetIcon(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::SetObserver(ui::TableModelObserver* observer) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_ = observer; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLTableModel::HasGroups() { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLTableModel::Groups TemplateURLTableModel::GetGroups() { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Groups groups; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Group search_engine_group; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_engine_group.title = 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_engine_group.id = kMainGroupID; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groups.push_back(search_engine_group); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Group other_group; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_group.title = 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_group.id = kOtherGroupID; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groups.push_back(other_group); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Group extension_group; 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_group.title = 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EXTENSIONS_SEPARATOR); 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_group.id = kExtensionGroupID; 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) groups.push_back(extension_group); 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return groups; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::GetGroupID(int row) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(row >= 0 && row < RowCount()); 244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (row < last_search_engine_index_) 245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return kMainGroupID; 246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return row < last_other_engine_index_ ? kOtherGroupID : kExtensionGroupID; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::Remove(int index) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the observer while we modify the model, that way we don't need to 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // worry about the model calling us back when we mutate it. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url = GetTemplateURL(index); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ModelEntry> entry(entries_[index]); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_.erase(entries_.begin() + index); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < last_search_engine_index_) 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) --last_search_engine_index_; 259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (index < last_other_engine_index_) 260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) --last_other_engine_index_; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer_) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->OnItemsRemoved(index, 1); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure to remove from the table model first, otherwise the 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TemplateURL would be freed. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->Remove(template_url); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::Add(int index, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& short_name, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& keyword, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index <= RowCount()); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!url.empty()); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLData data; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.short_name = short_name; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.SetKeyword(keyword); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.SetURL(url); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* turl = new TemplateURL(template_url_service_->profile(), data); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->Add(turl); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelEntry* entry = new ModelEntry(this, turl); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_.insert(entries_.begin() + index, entry); 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (index <= last_other_engine_index_) 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ++last_other_engine_index_; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer_) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->OnItemsAdded(index, 1); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::ModifyTemplateURL(int index, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title, 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& keyword, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index <= RowCount()); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!url.empty()); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url = GetTemplateURL(index); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The default search provider should support replacement. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(template_url_service_->GetDefaultSearchProvider() != template_url || 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url->SupportsReplacement()); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->ResetTemplateURL(template_url, title, keyword, url); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReloadIcon(index); // Also calls NotifyChanged(). 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::ReloadIcon(int index) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index < RowCount()); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_[index]->ResetIcon(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(index); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLTableModel::GetTemplateURL(int index) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entries_[index]->template_url(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::IndexOfTemplateURL( 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* template_url) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<ModelEntry*>::iterator i = entries_.begin(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != entries_.end(); ++i) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelEntry* entry = *i; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->template_url() == template_url) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(i - entries_.begin()); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::MoveToMainGroup(int index) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < last_search_engine_index_) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; // Already in the main group. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelEntry* current_entry = entries_[index]; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_.erase(index + entries_.begin()); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer_) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->OnItemsRemoved(index, 1); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int new_index = last_search_engine_index_++; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_.insert(entries_.begin() + new_index, current_entry); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer_) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->OnItemsAdded(new_index, 1); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_index; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::MakeDefaultTemplateURL(int index) { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < 0 || index >= RowCount()) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* keyword = GetTemplateURL(index); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* current_default = 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->GetDefaultSearchProvider(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_default == keyword) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->SetDefaultSearchProvider(keyword); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The formatting of the default engine is different; notify the table that 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // both old and new entries have changed. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_default != NULL) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_index = IndexOfTemplateURL(current_default); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current_default may not be in the list of TemplateURLs if the database is 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // corrupt and the default TemplateURL is used from preferences 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_index >= 0) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(old_index); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int new_index = IndexOfTemplateURL(keyword); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(new_index); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the new default is in the main group. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MoveToMainGroup(index); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::NotifyChanged(int index) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer_) { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(index, 0); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->OnItemsChanged(index, 1); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::FaviconAvailable(ModelEntry* entry) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ModelEntry*>::iterator i = 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(entries_.begin(), entries_.end(), entry); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(i != entries_.end()); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(static_cast<int>(i - entries_.begin())); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::OnTemplateURLServiceChanged() { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reload(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 396