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/custom_home_pages_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"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/table_model_observer.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks whether the given URL should count as one of the "current" pages.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true for all pages except dev tools and settings.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldAddPage(const GURL& url) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.is_empty())
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.SchemeIs(chrome::kChromeDevToolsScheme))
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.SchemeIs(chrome::kChromeUIScheme)) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (url.host() == chrome::kChromeUISettingsHost)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For a settings page, the path will start with "/settings" not "settings"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so find() will return 1, not 0.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (url.host() == chrome::kChromeUIUberHost &&
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url.path().find(chrome::kChromeUISettingsHost) == 1) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CustomHomePagesTableModel::Entry {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entry() : title_handle(0) {}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URL of the page.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Page title.  If this is empty, we'll display the URL as the entry.
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 title;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If non-zero, indicates we're loading the title for the page.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HistoryService::Handle title_handle;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomHomePagesTableModel::CustomHomePagesTableModel(Profile* profile)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_(NULL) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomHomePagesTableModel::~CustomHomePagesTableModel() {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::SetURLs(const std::vector<GURL>& urls) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_.resize(urls.size());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < urls.size(); ++i) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries_[i].url = urls[i];
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries_[i].title.erase();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadTitle(&(entries_[i]));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Complete change, so tell the view to just rebuild itself.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnModelChanged();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Move a number of existing entries to a new position, reordering the table.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We determine the range of elements affected by the move, save the moved
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * elements, compact the remaining ones, and re-insert moved elements.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Expects |index_list| to be ordered ascending.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::MoveURLs(int insert_before,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::vector<int>& index_list) {
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (index_list.empty()) return;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(insert_before >= 0 && insert_before <= RowCount());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The range of elements that needs to be reshuffled is [ |first|, |last| ).
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int first = std::min(insert_before, index_list.front());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last = std::max(insert_before, index_list.back() + 1);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the dragged elements. Also, adjust insertion point if it is before a
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dragged element.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Entry> moved_entries;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < index_list.size(); ++i) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    moved_entries.push_back(entries_[index_list[i]]);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index_list[i] == insert_before)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      insert_before++;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compact the range between beginning and insertion point, moving downwards.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t skip_count = 0;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = first; i < insert_before; ++i) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (skip_count < index_list.size() && index_list[skip_count] == i)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      skip_count++;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      entries_[i - skip_count] = entries_[i];
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving items down created a gap. We start compacting up after it.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first = insert_before;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  insert_before -= skip_count;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now compact up for elements after the insertion point.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  skip_count = 0;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = last - 1; i >= first; --i) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (skip_count < index_list.size() &&
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        index_list[index_list.size() - skip_count - 1] == i) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      skip_count++;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries_[i + skip_count] = entries_[i];
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Insert moved elements.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::copy(moved_entries.begin(), moved_entries.end(),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries_.begin() + insert_before);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Possibly large change, so tell the view to just rebuild itself.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnModelChanged();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::Add(int index, const GURL& url) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index <= RowCount());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_.insert(entries_.begin() + static_cast<size_t>(index), Entry());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_[index].url = url;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadTitle(&(entries_[index]));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnItemsAdded(index, 1);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::Remove(int index) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index < RowCount());
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entry* entry = &(entries_[index]);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel any pending load requests now so we don't deref a bogus pointer when
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we get the loaded notification.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->title_handle) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HistoryService* history_service = HistoryServiceFactory::GetForProfile(
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        profile_, Profile::EXPLICIT_ACCESS);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (history_service)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      history_service->CancelRequest(entry->title_handle);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_.erase(entries_.begin() + static_cast<size_t>(index));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnItemsRemoved(index, 1);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::SetToCurrentlyOpenPages() {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the current entries.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (RowCount())
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Remove(0);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And add all tabs for all open browsers with our profile.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int add_index = 0;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = *it;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser->profile() != profile_)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;  // Skip incognito browsers.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int tab_index = 0;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         tab_index < browser->tab_strip_model()->count();
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++tab_index) {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const GURL url =
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          browser->tab_strip_model()->GetWebContentsAt(tab_index)->GetURL();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ShouldAddPage(url))
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Add(add_index++, url);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<GURL> CustomHomePagesTableModel::GetURLs() {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<GURL> urls(entries_.size());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < entries_.size(); ++i)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    urls[i] = entries_[i].url;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return urls;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomHomePagesTableModel::RowCount() {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(entries_.size());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
207d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)base::string16 CustomHomePagesTableModel::GetText(int row, int column_id) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(column_id == 0);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(row >= 0 && row < RowCount());
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entries_[row].title.empty() ? FormattedURL(row) : entries_[row].title;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
213d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)base::string16 CustomHomePagesTableModel::GetTooltip(int row) {
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return entries_[row].title.empty() ? base::string16() :
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringFUTF16(IDS_OPTIONS_STARTUP_PAGE_TOOLTIP,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 entries_[row].title, FormattedURL(row));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::SetObserver(ui::TableModelObserver* observer) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_ = observer;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::LoadTitle(Entry* entry) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HistoryService* history_service = HistoryServiceFactory::GetForProfile(
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        profile_, Profile::EXPLICIT_ACCESS);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->title_handle = history_service->QueryURL(entry->url, false,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &history_query_consumer_,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&CustomHomePagesTableModel::OnGotTitle,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::OnGotTitle(HistoryService::Handle handle,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool found_url,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const history::URLRow* row,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           history::VisitVector* visits) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int entry_index;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entry* entry =
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetEntryByLoadHandle(&Entry::title_handle, handle, &entry_index);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The URLs changed before we were called back.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->title_handle = 0;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_url && !row->title().empty()) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->title = row->title();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (observer_)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_->OnItemsChanged(static_cast<int>(entry_index), 1);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomHomePagesTableModel::Entry*
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CustomHomePagesTableModel::GetEntryByLoadHandle(
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelableRequestProvider::Handle Entry::* member,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelableRequestProvider::Handle handle,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* index) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < entries_.size(); ++i) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entries_[i].*member == handle) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *index = static_cast<int>(i);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &entries_[i];
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
267d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)base::string16 CustomHomePagesTableModel::FormattedURL(int row) const {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string languages =
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 url = net::FormatUrl(entries_[row].url, languages);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url = base::i18n::GetDisplayStringInLTRDirectionality(url);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
274