Index: chrome/browser/chromeos/drive/search_metadata.cc |
diff --git a/chrome/browser/chromeos/drive/search_metadata.cc b/chrome/browser/chromeos/drive/search_metadata.cc |
deleted file mode 100644 |
index 31b9e308984fe0612b3d76dce96687cf683f88f3..0000000000000000000000000000000000000000 |
--- a/chrome/browser/chromeos/drive/search_metadata.cc |
+++ /dev/null |
@@ -1,335 +0,0 @@ |
-// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/chromeos/drive/search_metadata.h" |
- |
-#include <algorithm> |
-#include <queue> |
- |
-#include "base/bind.h" |
-#include "base/i18n/string_search.h" |
-#include "base/metrics/histogram.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/time/time.h" |
-#include "components/drive/drive_api_util.h" |
-#include "components/drive/file_system_core_util.h" |
-#include "net/base/escape.h" |
- |
-namespace drive { |
-namespace internal { |
- |
-namespace { |
- |
-struct ResultCandidate { |
- ResultCandidate(const std::string& local_id, |
- const ResourceEntry& entry, |
- const std::string& highlighted_base_name) |
- : local_id(local_id), |
- entry(entry), |
- highlighted_base_name(highlighted_base_name) { |
- } |
- |
- std::string local_id; |
- ResourceEntry entry; |
- std::string highlighted_base_name; |
-}; |
- |
-// Used to sort the result candidates per the last accessed/modified time. The |
-// recently accessed/modified files come first. |
-bool CompareByTimestamp(const ResourceEntry& a, const ResourceEntry& b) { |
- const PlatformFileInfoProto& a_file_info = a.file_info(); |
- const PlatformFileInfoProto& b_file_info = b.file_info(); |
- |
- if (a_file_info.last_accessed() != b_file_info.last_accessed()) |
- return a_file_info.last_accessed() > b_file_info.last_accessed(); |
- |
- // When the entries have the same last access time (which happens quite often |
- // because Drive server doesn't set the field until an entry is viewed via |
- // drive.google.com), we use last modified time as the tie breaker. |
- return a_file_info.last_modified() > b_file_info.last_modified(); |
-} |
- |
-struct ResultCandidateComparator { |
- bool operator()(const ResultCandidate* a, const ResultCandidate* b) const { |
- return CompareByTimestamp(a->entry, b->entry); |
- } |
-}; |
- |
-// A wrapper of std::priority_queue which deals with pointers of values. |
-template<typename T, typename Compare> |
-class ScopedPriorityQueue { |
- public: |
- ScopedPriorityQueue() {} |
- |
- ~ScopedPriorityQueue() { |
- while (!empty()) |
- pop(); |
- } |
- |
- bool empty() const { return queue_.empty(); } |
- |
- size_t size() const { return queue_.size(); } |
- |
- const T* top() const { return queue_.top(); } |
- |
- void push(T* x) { queue_.push(x); } |
- |
- void pop() { |
- // Keep top alive for the pop() call so that debug checks can access |
- // underlying data (e.g. validating heap property of the priority queue |
- // will call the comparator). |
- T* saved_top = queue_.top(); |
- queue_.pop(); |
- delete saved_top; |
- } |
- |
- private: |
- std::priority_queue<T*, std::vector<T*>, Compare> queue_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ScopedPriorityQueue); |
-}; |
- |
-// Classifies the given entry as hidden if it's not under specific directories. |
-class HiddenEntryClassifier { |
- public: |
- HiddenEntryClassifier(ResourceMetadata* metadata, |
- const std::string& mydrive_local_id) |
- : metadata_(metadata) { |
- // Only things under My Drive and drive/other are not hidden. |
- is_hiding_child_[mydrive_local_id] = false; |
- is_hiding_child_[util::kDriveOtherDirLocalId] = false; |
- |
- // Everything else is hidden, including the directories mentioned above |
- // themselves. |
- is_hiding_child_[""] = true; |
- } |
- |
- // |result| is set to true if |entry| is hidden. |
- FileError IsHidden(const ResourceEntry& entry, bool* result) { |
- // Look up for parents recursively. |
- std::vector<std::string> undetermined_ids; |
- undetermined_ids.push_back(entry.parent_local_id()); |
- |
- std::map<std::string, bool>::iterator it = |
- is_hiding_child_.find(undetermined_ids.back()); |
- for (; it == is_hiding_child_.end(); |
- it = is_hiding_child_.find(undetermined_ids.back())) { |
- ResourceEntry parent; |
- FileError error = |
- metadata_->GetResourceEntryById(undetermined_ids.back(), &parent); |
- if (error != FILE_ERROR_OK) |
- return error; |
- undetermined_ids.push_back(parent.parent_local_id()); |
- } |
- |
- // Cache the result. |
- undetermined_ids.pop_back(); // The last one is already in the map. |
- for (size_t i = 0; i < undetermined_ids.size(); ++i) |
- is_hiding_child_[undetermined_ids[i]] = it->second; |
- |
- *result = it->second; |
- return FILE_ERROR_OK; |
- } |
- |
- private: |
- ResourceMetadata* metadata_; |
- |
- // local ID to is_hidden map. |
- std::map<std::string, bool> is_hiding_child_; |
-}; |
- |
-// Used to implement SearchMetadata. |
-// Adds entry to the result when appropriate. |
-// In particular, if |query| is non-null, only adds files with the name matching |
-// the query. |
-FileError MaybeAddEntryToResult( |
- ResourceMetadata* resource_metadata, |
- ResourceMetadata::Iterator* it, |
- base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents* query, |
- const SearchMetadataPredicate& predicate, |
- size_t at_most_num_matches, |
- HiddenEntryClassifier* hidden_entry_classifier, |
- ScopedPriorityQueue<ResultCandidate, ResultCandidateComparator>* |
- result_candidates) { |
- DCHECK_GE(at_most_num_matches, result_candidates->size()); |
- |
- const ResourceEntry& entry = it->GetValue(); |
- |
- // If the candidate set is already full, and this |entry| is old, do nothing. |
- // We perform this check first in order to avoid the costly find-and-highlight |
- // or FilePath lookup as much as possible. |
- if (result_candidates->size() == at_most_num_matches && |
- !CompareByTimestamp(entry, result_candidates->top()->entry)) |
- return FILE_ERROR_OK; |
- |
- // Add |entry| to the result if the entry is eligible for the given |
- // |options| and matches the query. The base name of the entry must |
- // contain |query| to match the query. |
- std::string highlighted; |
- if (!predicate.Run(entry) || |
- (query && !FindAndHighlight(entry.base_name(), query, &highlighted))) |
- return FILE_ERROR_OK; |
- |
- // Hidden entry should not be returned. |
- bool hidden = false; |
- FileError error = hidden_entry_classifier->IsHidden(entry, &hidden); |
- if (error != FILE_ERROR_OK || hidden) |
- return error; |
- |
- // Make space for |entry| when appropriate. |
- if (result_candidates->size() == at_most_num_matches) |
- result_candidates->pop(); |
- result_candidates->push(new ResultCandidate(it->GetID(), entry, highlighted)); |
- return FILE_ERROR_OK; |
-} |
- |
-// Implements SearchMetadata(). |
-FileError SearchMetadataOnBlockingPool(ResourceMetadata* resource_metadata, |
- const std::string& query_text, |
- const SearchMetadataPredicate& predicate, |
- int at_most_num_matches, |
- MetadataSearchResultVector* results) { |
- ScopedPriorityQueue<ResultCandidate, |
- ResultCandidateComparator> result_candidates; |
- |
- // Prepare data structure for searching. |
- base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents query( |
- base::UTF8ToUTF16(query_text)); |
- |
- // Prepare an object to filter out hidden entries. |
- ResourceEntry mydrive; |
- FileError error = resource_metadata->GetResourceEntryByPath( |
- util::GetDriveMyDriveRootPath(), &mydrive); |
- if (error != FILE_ERROR_OK) |
- return error; |
- HiddenEntryClassifier hidden_entry_classifier(resource_metadata, |
- mydrive.local_id()); |
- |
- // Iterate over entries. |
- scoped_ptr<ResourceMetadata::Iterator> it = resource_metadata->GetIterator(); |
- for (; !it->IsAtEnd(); it->Advance()) { |
- FileError error = MaybeAddEntryToResult( |
- resource_metadata, it.get(), query_text.empty() ? NULL : &query, |
- predicate, at_most_num_matches, &hidden_entry_classifier, |
- &result_candidates); |
- if (error != FILE_ERROR_OK) |
- return error; |
- } |
- |
- // Prepare the result. |
- for (; !result_candidates.empty(); result_candidates.pop()) { |
- const ResultCandidate& candidate = *result_candidates.top(); |
- // The path field of entries in result_candidates are empty at this point, |
- // because we don't want to run the expensive metadata DB look up except for |
- // the final results. Hence, here we fill the part. |
- base::FilePath path; |
- error = resource_metadata->GetFilePath(candidate.local_id, &path); |
- if (error != FILE_ERROR_OK) |
- return error; |
- bool is_directory = candidate.entry.file_info().is_directory(); |
- results->push_back(MetadataSearchResult( |
- path, is_directory, candidate.highlighted_base_name, |
- candidate.entry.file_specific_info().md5())); |
- } |
- |
- // Reverse the order here because |result_candidates| puts the most |
- // uninteresting candidate at the top. |
- std::reverse(results->begin(), results->end()); |
- |
- return FILE_ERROR_OK; |
-} |
- |
-// Runs the SearchMetadataCallback and updates the histogram. |
-void RunSearchMetadataCallback(const SearchMetadataCallback& callback, |
- const base::TimeTicks& start_time, |
- scoped_ptr<MetadataSearchResultVector> results, |
- FileError error) { |
- if (error != FILE_ERROR_OK) |
- results.reset(); |
- callback.Run(error, results.Pass()); |
- |
- UMA_HISTOGRAM_TIMES("Drive.SearchMetadataTime", |
- base::TimeTicks::Now() - start_time); |
-} |
- |
-} // namespace |
- |
-void SearchMetadata( |
- scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, |
- ResourceMetadata* resource_metadata, |
- const std::string& query, |
- const SearchMetadataPredicate& predicate, |
- size_t at_most_num_matches, |
- const SearchMetadataCallback& callback) { |
- DCHECK(!callback.is_null()); |
- |
- const base::TimeTicks start_time = base::TimeTicks::Now(); |
- |
- scoped_ptr<MetadataSearchResultVector> results( |
- new MetadataSearchResultVector); |
- MetadataSearchResultVector* results_ptr = results.get(); |
- base::PostTaskAndReplyWithResult( |
- blocking_task_runner.get(), FROM_HERE, |
- base::Bind(&SearchMetadataOnBlockingPool, resource_metadata, query, |
- predicate, at_most_num_matches, results_ptr), |
- base::Bind(&RunSearchMetadataCallback, callback, start_time, |
- base::Passed(&results))); |
-} |
- |
-bool MatchesType(int options, const ResourceEntry& entry) { |
- if ((options & SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS) && |
- entry.file_specific_info().is_hosted_document()) |
- return false; |
- |
- if ((options & SEARCH_METADATA_EXCLUDE_DIRECTORIES) && |
- entry.file_info().is_directory()) |
- return false; |
- |
- if (options & SEARCH_METADATA_SHARED_WITH_ME) |
- return entry.shared_with_me(); |
- |
- if (options & SEARCH_METADATA_OFFLINE) { |
- if (entry.file_specific_info().is_hosted_document()) { |
- // Not all hosted documents are cached by Drive offline app. |
- // https://support.google.com/drive/answer/2375012 |
- std::string mime_type = entry.file_specific_info().content_mime_type(); |
- return mime_type == drive::util::kGoogleDocumentMimeType || |
- mime_type == drive::util::kGoogleSpreadsheetMimeType || |
- mime_type == drive::util::kGooglePresentationMimeType || |
- mime_type == drive::util::kGoogleDrawingMimeType; |
- } else { |
- return entry.file_specific_info().cache_state().is_present(); |
- } |
- } |
- |
- return true; |
-} |
- |
-bool FindAndHighlight( |
- const std::string& text, |
- base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents* query, |
- std::string* highlighted_text) { |
- DCHECK(query); |
- DCHECK(highlighted_text); |
- highlighted_text->clear(); |
- |
- base::string16 text16 = base::UTF8ToUTF16(text); |
- size_t match_start = 0; |
- size_t match_length = 0; |
- if (!query->Search(text16, &match_start, &match_length)) |
- return false; |
- |
- base::string16 pre = text16.substr(0, match_start); |
- base::string16 match = text16.substr(match_start, match_length); |
- base::string16 post = text16.substr(match_start + match_length); |
- highlighted_text->append(net::EscapeForHTML(base::UTF16ToUTF8(pre))); |
- highlighted_text->append("<b>"); |
- highlighted_text->append(net::EscapeForHTML(base::UTF16ToUTF8(match))); |
- highlighted_text->append("</b>"); |
- highlighted_text->append(net::EscapeForHTML(base::UTF16ToUTF8(post))); |
- return true; |
-} |
- |
-} // namespace internal |
-} // namespace drive |