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" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task/cancelable_task_tracker.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.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" 180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/favicon_base/favicon_types.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. 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static const 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(). 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetNativeImageNamed(IDR_DEFAULT_FAVICON).ToImageSkia(); 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. 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (template_url_->url_ref().IsValid( 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) model_->template_url_service()->search_terms_data())) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url(template_url_->url()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.is_valid()) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_url = TemplateURL::GenerateFaviconURL(url); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_url.is_valid()) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ = LOADING; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_service->GetFaviconImage( 1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_url, 1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FAVICON, 1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch gfx::kFaviconSize, 1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(&ModelEntry::OnFaviconDataAvailable, base::Unretained(this)), 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &tracker_); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch void OnFaviconDataAvailable( 1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const favicon_base::FaviconImageResult& image_result) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_state_ = LOADED; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_result.image.IsEmpty()) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ = image_result.image.AsImageSkia(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->FaviconAvailable(this); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia favicon_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadState load_state_; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLTableModel* model_; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker tracker_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ModelEntry); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TemplateURLTableModel ----------------------------------------- 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLTableModel::TemplateURLTableModel( 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLService* template_url_service) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : observer_(NULL), 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_(template_url_service) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(template_url_service); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->Load(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reload(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLTableModel::~TemplateURLTableModel() { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&entries_); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_.clear(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::Reload() { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&entries_); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_.clear(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLService::TemplateURLVector urls = 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->GetTemplateURLs(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<ModelEntry*> default_entries, other_entries, extension_entries; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keywords that can be made the default first. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (TemplateURLService::TemplateURLVector::iterator i = urls.begin(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != urls.end(); ++i) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url = *i; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: we don't use ShowInDefaultList here to avoid items bouncing around 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the lists while editing. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (template_url->show_in_default_list()) 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default_entries.push_back(new ModelEntry(this, template_url)); 1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else if (template_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION) 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_entries.push_back(new ModelEntry(this, template_url)); 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) else 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) other_entries.push_back(new ModelEntry(this, template_url)); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_search_engine_index_ = static_cast<int>(default_entries.size()); 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_other_engine_index_ = last_search_engine_index_ + 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<int>(other_entries.size()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entries_.insert(entries_.end(), 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default_entries.begin(), 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default_entries.end()); 172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entries_.insert(entries_.end(), 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) other_entries.begin(), 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) other_entries.end()); 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entries_.insert(entries_.end(), 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_entries.begin(), 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_entries.end()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer_) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->OnModelChanged(); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::RowCount() { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(entries_.size()); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 TemplateURLTableModel::GetText(int row, int col_id) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(row >= 0 && row < RowCount()); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* url = entries_[row]->template_url(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (col_id == IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN) { 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 url_short_name = url->short_name(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(xji): Consider adding a special case if the short name is a URL, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since those should always be displayed LTR. Please refer to 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/6726 for more information. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::AdjustStringForLocaleDirection(&url_short_name); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (template_url_service_->GetDefaultSearchProvider() == url) ? 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16(IDS_SEARCH_ENGINES_EDITOR_DEFAULT_ENGINE, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_short_name) : url_short_name; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN, col_id); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keyword should be domain name. Force it to have LTR directionality. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::i18n::GetDisplayStringInLTRDirectionality(url->keyword()); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkia TemplateURLTableModel::GetIcon(int row) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(row >= 0 && row < RowCount()); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entries_[row]->GetIcon(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::SetObserver(ui::TableModelObserver* observer) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_ = observer; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLTableModel::HasGroups() { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLTableModel::Groups TemplateURLTableModel::GetGroups() { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Groups groups; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Group search_engine_group; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_engine_group.title = 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_engine_group.id = kMainGroupID; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groups.push_back(search_engine_group); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Group other_group; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_group.title = 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other_group.id = kOtherGroupID; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) groups.push_back(other_group); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Group extension_group; 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_group.title = 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EXTENSIONS_SEPARATOR); 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_group.id = kExtensionGroupID; 240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) groups.push_back(extension_group); 241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return groups; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::GetGroupID(int row) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(row >= 0 && row < RowCount()); 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (row < last_search_engine_index_) 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return kMainGroupID; 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return row < last_other_engine_index_ ? kOtherGroupID : kExtensionGroupID; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::Remove(int index) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the observer while we modify the model, that way we don't need to 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // worry about the model calling us back when we mutate it. 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url = GetTemplateURL(index); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch scoped_ptr<ModelEntry> entry(RemoveEntry(index)); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure to remove from the table model first, otherwise the 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TemplateURL would be freed. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->Remove(template_url); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::Add(int index, 267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& short_name, 268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& keyword, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index <= RowCount()); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!url.empty()); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLData data; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.short_name = short_name; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.SetKeyword(keyword); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.SetURL(url); 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) TemplateURL* turl = new TemplateURL(data); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->Add(turl); 27958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch scoped_ptr<ModelEntry> entry(new ModelEntry(this, turl)); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 28158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch AddEntry(index, entry.Pass()); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::ModifyTemplateURL(int index, 285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title, 286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& keyword, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index <= RowCount()); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!url.empty()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* template_url = GetTemplateURL(index); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The default search provider should support replacement. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(template_url_service_->GetDefaultSearchProvider() != template_url || 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) template_url->SupportsReplacement( 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) template_url_service_->search_terms_data())); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->ResetTemplateURL(template_url, title, keyword, url); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReloadIcon(index); // Also calls NotifyChanged(). 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::ReloadIcon(int index) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index < RowCount()); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_[index]->ResetIcon(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(index); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLTableModel::GetTemplateURL(int index) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entries_[index]->template_url(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::IndexOfTemplateURL( 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* template_url) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<ModelEntry*>::iterator i = entries_.begin(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != entries_.end(); ++i) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelEntry* entry = *i; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->template_url() == template_url) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(i - entries_.begin()); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::MoveToMainGroup(int index) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < last_search_engine_index_) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; // Already in the main group. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch scoped_ptr<ModelEntry> current_entry(RemoveEntry(index)); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int new_index = last_search_engine_index_++; 33058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch AddEntry(new_index, current_entry.Pass()); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_index; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TemplateURLTableModel::MakeDefaultTemplateURL(int index) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < 0 || index >= RowCount()) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURL* keyword = GetTemplateURL(index); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* current_default = 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->GetDefaultSearchProvider(); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_default == keyword) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->RemoveObserver(this); 3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu template_url_service_->SetUserSelectedDefaultSearchProvider(keyword); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->AddObserver(this); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The formatting of the default engine is different; notify the table that 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // both old and new entries have changed. 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_default != NULL) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_index = IndexOfTemplateURL(current_default); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current_default may not be in the list of TemplateURLs if the database is 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // corrupt and the default TemplateURL is used from preferences 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_index >= 0) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(old_index); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int new_index = IndexOfTemplateURL(keyword); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(new_index); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the new default is in the main group. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MoveToMainGroup(index); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::NotifyChanged(int index) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer_) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(index, 0); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->OnItemsChanged(index, 1); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::FaviconAvailable(ModelEntry* entry) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ModelEntry*>::iterator i = 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(entries_.begin(), entries_.end(), entry); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(i != entries_.end()); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyChanged(static_cast<int>(i - entries_.begin())); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLTableModel::OnTemplateURLServiceChanged() { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reload(); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 38358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 38458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochscoped_ptr<ModelEntry> TemplateURLTableModel::RemoveEntry(int index) { 38558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch scoped_ptr<ModelEntry> entry(entries_[index]); 38658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch entries_.erase(index + entries_.begin()); 38758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (index < last_search_engine_index_) 38858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch --last_search_engine_index_; 38958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (index < last_other_engine_index_) 39058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch --last_other_engine_index_; 39158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (observer_) 39258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch observer_->OnItemsRemoved(index, 1); 39358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch return entry.Pass(); 39458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch} 39558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 39658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochvoid TemplateURLTableModel::AddEntry(int index, scoped_ptr<ModelEntry> entry) { 39758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch entries_.insert(entries_.begin() + index, entry.release()); 39858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (index <= last_other_engine_index_) 39958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch ++last_other_engine_index_; 40058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (observer_) 40158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch observer_->OnItemsAdded(index, 1); 40258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch} 403