Commit message: None
CVE: CVE-2011-2782
CWE: CWE-264
Vulnerability description: The drag-and-drop implementation in Google Chrome before 13.0.782.107 on Linux does not properly enforce permissions for files, which allows user-assisted remote attackers to bypass intended access restrictions via unspecified vectors.

Project: Chrome

bool AreURLsInPageNavigation(const GURL& existing_url, const GURL& new_url) {
  if (existing_url == new_url || !new_url.has_ref()) {
    return false;
  }

  url_canon::Replacements<char> replacements;
  replacements.ClearRef();
  return existing_url.ReplaceComponents(replacements) ==
      new_url.ReplaceComponents(replacements);
}

Project: Chrome

bool NavigationController::CanViewSource() const {
  bool is_supported_mime_type = net::IsSupportedNonImageMimeType(
      tab_contents_->contents_mime_type().c_str());
  NavigationEntry* active_entry = GetActiveEntry();
  return active_entry && !active_entry->IsViewSourceMode() &&
    is_supported_mime_type;
}

Project: Chrome

void NavigationController::CancelPendingReload() {
  DCHECK(pending_reload_ != NO_RELOAD);
  pending_reload_ = NO_RELOAD;
}

Project: Chrome

NavigationType::Type NavigationController::ClassifyNavigation(
    const ViewHostMsg_FrameNavigate_Params& params) const {
  if (params.page_id == -1) {
    return NavigationType::NAV_IGNORE;
  }

  if (params.page_id > tab_contents_->GetMaxPageID()) {
    if (PageTransition::IsMainFrame(params.transition))
      return NavigationType::NEW_PAGE;

    if (!GetLastCommittedEntry())
      return NavigationType::NAV_IGNORE;

    return NavigationType::NEW_SUBFRAME;
  }

  int existing_entry_index = GetEntryIndexWithPageID(
      tab_contents_->GetSiteInstance(),
      params.page_id);
  if (existing_entry_index == -1) {
    NOTREACHED();
    return NavigationType::NAV_IGNORE;
  }
  NavigationEntry* existing_entry = entries_[existing_entry_index].get();

  if (!PageTransition::IsMainFrame(params.transition)) {
    DCHECK(GetLastCommittedEntry());
    return NavigationType::AUTO_SUBFRAME;
  }

  if (pending_entry_ &&
      existing_entry != pending_entry_ &&
      pending_entry_->page_id() == -1 &&
      existing_entry == GetLastCommittedEntry()) {
    return NavigationType::SAME_PAGE;
  }

  if (AreURLsInPageNavigation(existing_entry->url(), params.url))
    return NavigationType::IN_PAGE;

  return NavigationType::EXISTING_PAGE;
}

Project: Chrome

void ConfigureEntriesForRestore(
    std::vector<linked_ptr<NavigationEntry> >* entries,
    bool from_last_session) {
  for (size_t i = 0; i < entries->size(); ++i) {
    (*entries)[i]->set_transition_type(PageTransition::RELOAD);
    (*entries)[i]->set_restore_type(from_last_session ?
        NavigationEntry::RESTORE_LAST_SESSION :
        NavigationEntry::RESTORE_CURRENT_SESSION);
    SetContentStateIfEmpty((*entries)[i].get());
  }
}

Project: Chrome

void NavigationController::ContinuePendingReload() {
  if (pending_reload_ == NO_RELOAD) {
    NOTREACHED();
  } else {
    ReloadInternal(false, pending_reload_);
    pending_reload_ = NO_RELOAD;
  }
}

Project: Chrome

void NavigationController::CopyStateFrom(const NavigationController& source) {
  DCHECK(entry_count() == 0 && !pending_entry());

  if (source.entry_count() == 0)
    return;  // Nothing new to do.

  needs_reload_ = true;
  InsertEntriesFrom(source, source.entry_count());

  session_storage_namespace_ = source.session_storage_namespace_->Clone();

  FinishRestore(source.last_committed_entry_index_, false);
}

Project: Chrome

void NavigationController::CreateNavigationEntriesFromTabNavigations(
    const std::vector<TabNavigation>& navigations,
    std::vector<linked_ptr<NavigationEntry> >* entries) {
  int page_id = 0;
  for (std::vector<TabNavigation>::const_iterator i =
           navigations.begin(); i != navigations.end(); ++i, ++page_id) {
    linked_ptr<NavigationEntry> entry(i->ToNavigationEntry(page_id, profile_));
    entries->push_back(entry);
  }
}

Project: Chrome

NavigationEntry* NavigationController::CreateNavigationEntry(
    const GURL& url, const GURL& referrer, PageTransition::Type transition,
    Profile* profile) {
  GURL loaded_url(url);
  bool reverse_on_redirect = false;
  BrowserURLHandler::RewriteURLIfNecessary(
      &loaded_url, profile, &reverse_on_redirect);

  NavigationEntry* entry = new NavigationEntry(
      NULL,  // The site instance for tabs is sent on navigation
      -1,
      loaded_url,
      referrer,
      string16(),
      transition);
  entry->set_virtual_url(url);
  entry->set_user_typed_url(url);
  entry->set_update_virtual_url_with_url(reverse_on_redirect);
  return entry;
}

Project: Chrome

void NavigationController::DiscardTransientEntry() {
  if (transient_entry_index_ == -1)
    return;
  entries_.erase(entries_.begin() + transient_entry_index_);
  if (last_committed_entry_index_ > transient_entry_index_)
    last_committed_entry_index_--;
  transient_entry_index_ = -1;
}

Project: Chrome

void NavigationController::FinishRestore(int selected_index,
                                         bool from_last_session) {
  DCHECK(selected_index >= 0 && selected_index < entry_count());
  ConfigureEntriesForRestore(&entries_, from_last_session);

  set_max_restored_page_id(static_cast<int32>(entry_count()));

  last_committed_entry_index_ = selected_index;
}

Project: Chrome

void NavigationController::GoBack() {
  if (!CanGoBack()) {
    NOTREACHED();
    return;
  }

  if (tab_contents_->interstitial_page()) {
    tab_contents_->interstitial_page()->DontProceed();
    return;
  }

  int current_index = GetCurrentEntryIndex();

  DiscardNonCommittedEntries();

  pending_entry_index_ = current_index - 1;
  entries_[pending_entry_index_]->set_transition_type(
      entries_[pending_entry_index_]->transition_type() |
      PageTransition::FORWARD_BACK);
  NavigateToPendingEntry(NO_RELOAD);
}

Project: Chrome

void NavigationController::GoForward() {
  if (!CanGoForward()) {
    NOTREACHED();
    return;
  }

  if (tab_contents_->interstitial_page()) {
    tab_contents_->interstitial_page()->CancelForNavigation();
  }

  bool transient = (transient_entry_index_ != -1);

  int current_index = GetCurrentEntryIndex();

  DiscardNonCommittedEntries();

  pending_entry_index_ = current_index;
  if (!transient)
    pending_entry_index_++;

  entries_[pending_entry_index_]->set_transition_type(
      entries_[pending_entry_index_]->transition_type() |
      PageTransition::FORWARD_BACK);
  NavigateToPendingEntry(NO_RELOAD);
}

Project: Chrome

void NavigationController::GoToIndex(int index) {
  if (index < 0 || index >= static_cast<int>(entries_.size())) {
    NOTREACHED();
    return;
  }

  if (transient_entry_index_ != -1) {
    if (index == transient_entry_index_) {
      return;
    }
    if (index > transient_entry_index_) {
      index--;
    }
  }

  if (tab_contents_->interstitial_page()) {
    if (index == GetCurrentEntryIndex() - 1) {
      tab_contents_->interstitial_page()->DontProceed();
      return;
    } else {
      tab_contents_->interstitial_page()->CancelForNavigation();
    }
  }

  DiscardNonCommittedEntries();

  pending_entry_index_ = index;
  entries_[pending_entry_index_]->set_transition_type(
      entries_[pending_entry_index_]->transition_type() |
      PageTransition::FORWARD_BACK);
  NavigateToPendingEntry(NO_RELOAD);
}

Project: Chrome

bool NavigationController::IsInitialNavigation() {
  return last_document_loaded_.is_null();
}

Project: Chrome

void NavigationController::LoadIfNecessary() {
  if (!needs_reload_)
    return;

  pending_entry_index_ = last_committed_entry_index_;
  NavigateToPendingEntry(NO_RELOAD);
}

Project: Chrome

void NavigationController::LoadURL(const GURL& url, const GURL& referrer,
                                   PageTransition::Type transition) {
  needs_reload_ = false;

  NavigationEntry* entry = CreateNavigationEntry(url, referrer, transition,
                                                 profile_);

  LoadEntry(entry);
}

Project: Chrome

void NavigationController::NavigateToPendingEntry(ReloadType reload_type) {
  needs_reload_ = false;

  if (!pending_entry_) {
    DCHECK_NE(pending_entry_index_, -1);
    pending_entry_ = entries_[pending_entry_index_].get();
  }

  if (!tab_contents_->NavigateToPendingEntry(reload_type))
    DiscardNonCommittedEntries();
}

Project: Chrome

NavigationController::NavigationController(
    TabContents* contents,
    Profile* profile,
    SessionStorageNamespace* session_storage_namespace)
    : profile_(profile),
      pending_entry_(NULL),
      last_committed_entry_index_(-1),
      pending_entry_index_(-1),
      transient_entry_index_(-1),
      tab_contents_(contents),
      max_restored_page_id_(-1),
      ALLOW_THIS_IN_INITIALIZER_LIST(ssl_manager_(this)),
      needs_reload_(false),
      session_storage_namespace_(session_storage_namespace),
      pending_reload_(NO_RELOAD) {
  DCHECK(profile_);
  if (!session_storage_namespace_) {
    session_storage_namespace_ = new SessionStorageNamespace(
        profile_->GetWebKitContext());
  }
}

Project: Chrome

void NavigationController::PruneAllButActive() {
  if (transient_entry_index_ != -1) {
    DCHECK_EQ(entry_count() - 1, transient_entry_index_);
    entries_.erase(entries_.begin(), entries_.begin() + transient_entry_index_);
    transient_entry_index_ = 0;
    last_committed_entry_index_ = -1;
    pending_entry_index_ = -1;
  } else if (!pending_entry_) {
    if (!entry_count())
      return;

    DCHECK(last_committed_entry_index_ >= 0);
    entries_.erase(entries_.begin(),
                   entries_.begin() + last_committed_entry_index_);
    entries_.erase(entries_.begin() + 1, entries_.end());
    last_committed_entry_index_ = 0;
  } else if (pending_entry_index_ != -1) {
    entries_.erase(entries_.begin(), entries_.begin() + pending_entry_index_);
    entries_.erase(entries_.begin() + 1, entries_.end());
    pending_entry_index_ = 0;
    last_committed_entry_index_ = 0;
  } else {
    pending_entry_index_ = -1;
    last_committed_entry_index_ = -1;
    entries_.clear();
  }

  if (tab_contents_->interstitial_page()) {
    tab_contents_->interstitial_page()->set_reload_on_dont_proceed(true);
  }
}

Project: Chrome

void NavigationController::Reload(bool check_for_repost) {
  ReloadInternal(check_for_repost, RELOAD);
}

Project: Chrome

void NavigationController::ReloadIgnoringCache(bool check_for_repost) {
  ReloadInternal(check_for_repost, RELOAD_IGNORING_CACHE);
}

Project: Chrome

void NavigationController::ReloadInternal(bool check_for_repost,
                                          ReloadType reload_type) {
  if (transient_entry_index_ != -1)
    return;

  DiscardNonCommittedEntriesInternal();
  int current_index = GetCurrentEntryIndex();
  if (current_index == -1) {
    return;
  }

  if (check_for_repost_ && check_for_repost &&
      GetEntryAtIndex(current_index)->has_post_data()) {
    NotificationService::current()->Notify(
        NotificationType::REPOST_WARNING_SHOWN,
        Source<NavigationController>(this),
        NotificationService::NoDetails());

    pending_reload_ = reload_type;
    tab_contents_->Activate();
    tab_contents_->delegate()->ShowRepostFormWarningDialog(tab_contents_);
  } else {
    DiscardNonCommittedEntriesInternal();

    pending_entry_index_ = current_index;
    entries_[pending_entry_index_]->set_transition_type(PageTransition::RELOAD);
    NavigateToPendingEntry(reload_type);
  }
}

Project: Chrome

void NavigationController::RemoveEntryAtIndex(int index,
                                              const GURL& default_url) {
  bool is_current = index == last_committed_entry_index_;
  RemoveEntryAtIndexInternal(index);
  if (is_current) {
    if (last_committed_entry_index_ != -1) {
      pending_entry_index_ = last_committed_entry_index_;
      NavigateToPendingEntry(NO_RELOAD);
    } else {
      LoadURL(default_url.is_empty() ? GURL("about:blank") : default_url,
              GURL(), PageTransition::START_PAGE);
    }
  }
}

Project: Chrome

void NavigationController::RendererDidNavigateInPage(
    const ViewHostMsg_FrameNavigate_Params& params, bool* did_replace_entry) {
  DCHECK(PageTransition::IsMainFrame(params.transition)) <<
      "WebKit should only tell us about in-page navs for the main frame.";
  NavigationEntry* existing_entry = GetEntryWithPageID(
      tab_contents_->GetSiteInstance(),
      params.page_id);

  NavigationEntry* new_entry = new NavigationEntry(*existing_entry);
  new_entry->set_page_id(params.page_id);
  if (new_entry->update_virtual_url_with_url())
    UpdateVirtualURLToURL(new_entry, params.url);
  new_entry->set_url(params.url);

  *did_replace_entry = true;
  InsertOrReplaceEntry(new_entry, true);
}

Project: Chrome

void NavigationController::RendererDidNavigateNewSubframe(
    const ViewHostMsg_FrameNavigate_Params& params) {
  if (PageTransition::StripQualifier(params.transition) ==
      PageTransition::AUTO_SUBFRAME) {
    return;
  }

  DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee "
                                  << "that a last committed entry exists.";
  NavigationEntry* new_entry = new NavigationEntry(*GetLastCommittedEntry());
  new_entry->set_page_id(params.page_id);
  InsertOrReplaceEntry(new_entry, false);
}

Project: Chrome

void NavigationController::RendererDidNavigateToExistingPage(
    const ViewHostMsg_FrameNavigate_Params& params) {
  DCHECK(PageTransition::IsMainFrame(params.transition));

  int entry_index = GetEntryIndexWithPageID(tab_contents_->GetSiteInstance(),
                                            params.page_id);
  DCHECK(entry_index >= 0 &&
         entry_index < static_cast<int>(entries_.size()));
  NavigationEntry* entry = entries_[entry_index].get();

  entry->set_url(params.url);
  if (entry->update_virtual_url_with_url())
    UpdateVirtualURLToURL(entry, params.url);
  DCHECK(entry->site_instance() == NULL ||
         entry->site_instance() == tab_contents_->GetSiteInstance());
  entry->set_site_instance(tab_contents_->GetSiteInstance());

  entry->set_has_post_data(params.is_post);

  if (pending_entry_)
    DiscardNonCommittedEntriesInternal();

  last_committed_entry_index_ =
      GetEntryIndexWithPageID(tab_contents_->GetSiteInstance(), params.page_id);
}

Project: Chrome

void NavigationController::RendererDidNavigateToNewPage(
    const ViewHostMsg_FrameNavigate_Params& params, bool* did_replace_entry) {
  NavigationEntry* new_entry;
  if (pending_entry_) {
    new_entry = new NavigationEntry(*pending_entry_);

    new_entry->set_page_type(NORMAL_PAGE);
  } else {
    new_entry = new NavigationEntry;
  }

  new_entry->set_url(params.url);
  if (new_entry->update_virtual_url_with_url())
    UpdateVirtualURLToURL(new_entry, params.url);
  new_entry->set_referrer(params.referrer);
  new_entry->set_page_id(params.page_id);
  new_entry->set_transition_type(params.transition);
  new_entry->set_site_instance(tab_contents_->GetSiteInstance());
  new_entry->set_has_post_data(params.is_post);

  InsertOrReplaceEntry(new_entry, *did_replace_entry);
}

Project: Chrome

void NavigationController::RendererDidNavigateToSamePage(
    const ViewHostMsg_FrameNavigate_Params& params) {
  NavigationEntry* existing_entry = GetEntryWithPageID(
      tab_contents_->GetSiteInstance(),
      params.page_id);

  existing_entry->set_unique_id(pending_entry_->unique_id());

  if (existing_entry->update_virtual_url_with_url())
    UpdateVirtualURLToURL(existing_entry, params.url);
  existing_entry->set_url(params.url);

  DiscardNonCommittedEntries();
}

Project: Chrome

void NavigationController::RestoreFromState(
    const std::vector<TabNavigation>& navigations,
    int selected_navigation,
    bool from_last_session) {
  DCHECK(entry_count() == 0 && !pending_entry());
  DCHECK(selected_navigation >= 0 &&
         selected_navigation < static_cast<int>(navigations.size()));

  needs_reload_ = true;
  CreateNavigationEntriesFromTabNavigations(navigations, &entries_);

  FinishRestore(selected_navigation, from_last_session);
}

Project: Chrome

void NavigationController::UpdateVirtualURLToURL(
    NavigationEntry* entry, const GURL& new_url) {
  GURL new_virtual_url(new_url);
  if (BrowserURLHandler::ReverseURLRewrite(
          &new_virtual_url, entry->virtual_url(), profile_)) {
    entry->set_virtual_url(new_virtual_url);
  }
}

Project: Chrome

  void GetLastSession() {
    profile()->GetSessionService()->TabClosed(controller().window_id(),
                                              controller().session_id(),
                                              false);

    ReopenDatabase();
    Time close_time;

    session_helper_.ReadWindows(&windows_);
  }

Project: Chrome

  NavigationControllerHistoryTest()
      : url0("http://foo1"),
        url1("http://foo1"),
        url2("http://foo1"),
        profile_manager_(NULL) {
  }

Project: Chrome

  NavigationControllerTest() {}

Project: Chrome

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    if (type == NotificationType::NAV_LIST_PRUNED) {
      notification_count_++;
      details_ = *(Details<NavigationController::PrunedDetails>(details).ptr());
    }
  }

Project: Chrome

  explicit PrunedListener(NavigationController* controller)
      : notification_count_(0) {
    registrar_.Add(this, NotificationType::NAV_LIST_PRUNED,
                   Source<NavigationController>(controller));
  }

Project: Chrome

void RegisterForAllNavNotifications(TestNotificationTracker* tracker,
                                    NavigationController* controller) {
  tracker->ListenFor(NotificationType::NAV_ENTRY_COMMITTED,
                     Source<NavigationController>(controller));
  tracker->ListenFor(NotificationType::NAV_LIST_PRUNED,
                     Source<NavigationController>(controller));
  tracker->ListenFor(NotificationType::NAV_ENTRY_CHANGED,
                      Source<NavigationController>(controller));
 }

Project: Chrome

  void ReopenDatabase() {
    session_helper_.set_service(NULL);
    profile()->set_session_service(NULL);

    SessionService* service = new SessionService(profile());
    profile()->set_session_service(service);
    session_helper_.set_service(service);
  }

Project: Chrome

  virtual void SetUp() {
    NavigationControllerTest::SetUp();

    SessionService* service = new SessionService(profile());
    profile()->set_session_service(service);
    service->SetWindowType(window_id, Browser::TYPE_NORMAL);
    service->SetWindowBounds(window_id, gfx::Rect(0, 1, 2, 3), false);
    service->SetTabIndexInWindow(window_id,
                                 controller().session_id(), 0);
    controller().SetWindowID(window_id);

    session_helper_.set_service(service);
  }