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"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/history/history_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.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)
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (url.SchemeIs(content::kChromeDevToolsScheme))
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (url.SchemeIs(content::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 {
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Entry() : task_id(base::CancelableTaskTracker::kBadTaskId) {}
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)
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If not |base::CancelableTaskTracker::kBadTaskId|, indicates we're loading
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // the title for the page.
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::CancelableTaskTracker::TaskId task_id;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomHomePagesTableModel::CustomHomePagesTableModel(Profile* profile)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_(NULL) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomHomePagesTableModel::~CustomHomePagesTableModel() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::SetURLs(const std::vector<GURL>& urls) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_.resize(urls.size());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < urls.size(); ++i) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries_[i].url = urls[i];
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries_[i].title.erase();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadTitle(&(entries_[i]));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Complete change, so tell the view to just rebuild itself.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnModelChanged();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Move a number of existing entries to a new position, reordering the table.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We determine the range of elements affected by the move, save the moved
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * elements, compact the remaining ones, and re-insert moved elements.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Expects |index_list| to be ordered ascending.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::MoveURLs(int insert_before,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::vector<int>& index_list) {
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (index_list.empty()) return;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(insert_before >= 0 && insert_before <= RowCount());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The range of elements that needs to be reshuffled is [ |first|, |last| ).
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int first = std::min(insert_before, index_list.front());
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last = std::max(insert_before, index_list.back() + 1);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the dragged elements. Also, adjust insertion point if it is before a
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dragged element.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Entry> moved_entries;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < index_list.size(); ++i) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    moved_entries.push_back(entries_[index_list[i]]);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index_list[i] == insert_before)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      insert_before++;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compact the range between beginning and insertion point, moving downwards.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t skip_count = 0;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = first; i < insert_before; ++i) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (skip_count < index_list.size() && index_list[skip_count] == i)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      skip_count++;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      entries_[i - skip_count] = entries_[i];
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving items down created a gap. We start compacting up after it.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first = insert_before;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  insert_before -= skip_count;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now compact up for elements after the insertion point.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  skip_count = 0;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = last - 1; i >= first; --i) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (skip_count < index_list.size() &&
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        index_list[index_list.size() - skip_count - 1] == i) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      skip_count++;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries_[i + skip_count] = entries_[i];
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Insert moved elements.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::copy(moved_entries.begin(), moved_entries.end(),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries_.begin() + insert_before);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Possibly large change, so tell the view to just rebuild itself.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnModelChanged();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::Add(int index, const GURL& url) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index <= RowCount());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_.insert(entries_.begin() + static_cast<size_t>(index), Entry());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_[index].url = url;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadTitle(&(entries_[index]));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnItemsAdded(index, 1);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::Remove(int index) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index >= 0 && index < RowCount());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Entry* entry = &(entries_[index]);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel any pending load requests now so we don't deref a bogus pointer when
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we get the loaded notification.
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (entry->task_id != base::CancelableTaskTracker::kBadTaskId) {
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    task_tracker_.TryCancel(entry->task_id);
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    entry->task_id = base::CancelableTaskTracker::kBadTaskId;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entries_.erase(entries_.begin() + static_cast<size_t>(index));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer_)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnItemsRemoved(index, 1);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::SetToCurrentlyOpenPages() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the current entries.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (RowCount())
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Remove(0);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And add all tabs for all open browsers with our profile.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int add_index = 0;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser = *it;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (browser->profile() != profile_)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;  // Skip incognito browsers.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int tab_index = 0;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         tab_index < browser->tab_strip_model()->count();
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++tab_index) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const GURL url =
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          browser->tab_strip_model()->GetWebContentsAt(tab_index)->GetURL();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ShouldAddPage(url))
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Add(add_index++, url);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<GURL> CustomHomePagesTableModel::GetURLs() {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<GURL> urls(entries_.size());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < entries_.size(); ++i)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    urls[i] = entries_[i].url;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return urls;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomHomePagesTableModel::RowCount() {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(entries_.size());
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 CustomHomePagesTableModel::GetText(int row, int column_id) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(column_id == 0);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(row >= 0 && row < RowCount());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entries_[row].title.empty() ? FormattedURL(row) : entries_[row].title;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 CustomHomePagesTableModel::GetTooltip(int row) {
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return entries_[row].title.empty() ? base::string16() :
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringFUTF16(IDS_OPTIONS_STARTUP_PAGE_TOOLTIP,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 entries_[row].title, FormattedURL(row));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::SetObserver(ui::TableModelObserver* observer) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_ = observer;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomHomePagesTableModel::LoadTitle(Entry* entry) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HistoryService* history_service = HistoryServiceFactory::GetForProfile(
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        profile_, Profile::EXPLICIT_ACCESS);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service) {
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    entry->task_id = history_service->QueryURL(
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        entry->url,
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        false,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&CustomHomePagesTableModel::OnGotTitle,
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                   base::Unretained(this),
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                   entry->url),
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        &task_tracker_);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void CustomHomePagesTableModel::OnGotTitle(const GURL& entry_url,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool found_url,
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           const history::URLRow& row,
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           const history::VisitVector& visits) {
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Entry* entry = NULL;
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t entry_index = 0;
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < entries_.size(); ++i) {
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (entries_[i].url == entry_url) {
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      entry = &entries_[i];
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      entry_index = i;
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The URLs changed before we were called back.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  entry->task_id = base::CancelableTaskTracker::kBadTaskId;
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (found_url && !row.title().empty()) {
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    entry->title = row.title();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (observer_)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_->OnItemsChanged(static_cast<int>(entry_index), 1);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 CustomHomePagesTableModel::FormattedURL(int row) const {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string languages =
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 url = net::FormatUrl(entries_[row].url, languages);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url = base::i18n::GetDisplayStringInLTRDirectionality(url);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
268