| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/chromeos/drive/drive_webapps_registry.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <string> | |
| 9 #include <utility> | |
| 10 #include <vector> | |
| 11 | |
| 12 #include "base/files/file_path.h" | |
| 13 #include "base/string_util.h" | |
| 14 #include "base/utf_string_conversions.h" | |
| 15 #include "chrome/browser/chromeos/drive/file_system_util.h" | |
| 16 #include "chrome/browser/chromeos/drive/job_scheduler.h" | |
| 17 #include "chrome/browser/google_apis/drive_api_parser.h" | |
| 18 #include "content/public/browser/browser_thread.h" | |
| 19 | |
| 20 using content::BrowserThread; | |
| 21 | |
| 22 namespace drive { | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 // WebApp store URL prefix. | |
| 27 const char kStoreProductUrl[] = "https://chrome.google.com/webstore/"; | |
| 28 | |
| 29 // Extracts Web store id from its web store URL. | |
| 30 std::string GetWebStoreIdFromUrl(const GURL& url) { | |
| 31 if (!StartsWithASCII(url.spec(), kStoreProductUrl, false)) { | |
| 32 LOG(WARNING) << "Unrecognized product URL " << url.spec(); | |
| 33 return std::string(); | |
| 34 } | |
| 35 | |
| 36 base::FilePath path(url.path()); | |
| 37 std::vector<base::FilePath::StringType> components; | |
| 38 path.GetComponents(&components); | |
| 39 DCHECK_LE(2U, components.size()); // Coming from kStoreProductUrl | |
| 40 | |
| 41 // Return the last part of the path | |
| 42 return components[components.size() - 1]; | |
| 43 } | |
| 44 | |
| 45 // TODO(kochi): This is duplicate from gdata_wapi_parser.cc. | |
| 46 bool SortBySize(const google_apis::InstalledApp::IconList::value_type& a, | |
| 47 const google_apis::InstalledApp::IconList::value_type& b) { | |
| 48 return a.first < b.first; | |
| 49 } | |
| 50 | |
| 51 } // namespace | |
| 52 | |
| 53 // DriveWebAppInfo struct implementation. | |
| 54 | |
| 55 DriveWebAppInfo::DriveWebAppInfo( | |
| 56 const std::string& app_id, | |
| 57 const google_apis::InstalledApp::IconList& app_icons, | |
| 58 const google_apis::InstalledApp::IconList& document_icons, | |
| 59 const std::string& web_store_id, | |
| 60 const string16& app_name, | |
| 61 const string16& object_type, | |
| 62 bool is_primary_selector) | |
| 63 : app_id(app_id), | |
| 64 app_icons(app_icons), | |
| 65 document_icons(document_icons), | |
| 66 web_store_id(web_store_id), | |
| 67 app_name(app_name), | |
| 68 object_type(object_type), | |
| 69 is_primary_selector(is_primary_selector) { | |
| 70 } | |
| 71 | |
| 72 DriveWebAppInfo::~DriveWebAppInfo() { | |
| 73 } | |
| 74 | |
| 75 // FileSystem::WebAppFileSelector struct implementation. | |
| 76 | |
| 77 DriveWebAppsRegistry::WebAppFileSelector::WebAppFileSelector( | |
| 78 const GURL& product_link, | |
| 79 const google_apis::InstalledApp::IconList& app_icons, | |
| 80 const google_apis::InstalledApp::IconList& document_icons, | |
| 81 const string16& object_type, | |
| 82 const std::string& app_id, | |
| 83 bool is_primary_selector) | |
| 84 : product_link(product_link), | |
| 85 app_icons(app_icons), | |
| 86 document_icons(document_icons), | |
| 87 object_type(object_type), | |
| 88 app_id(app_id), | |
| 89 is_primary_selector(is_primary_selector) { | |
| 90 } | |
| 91 | |
| 92 DriveWebAppsRegistry::WebAppFileSelector::~WebAppFileSelector() { | |
| 93 } | |
| 94 | |
| 95 // DriveWebAppsRegistry implementation. | |
| 96 | |
| 97 DriveWebAppsRegistry::DriveWebAppsRegistry(JobScheduler* scheduler) | |
| 98 : scheduler_(scheduler), | |
| 99 weak_ptr_factory_(this) { | |
| 100 } | |
| 101 | |
| 102 DriveWebAppsRegistry::~DriveWebAppsRegistry() { | |
| 103 STLDeleteValues(&webapp_extension_map_); | |
| 104 STLDeleteValues(&webapp_mimetypes_map_); | |
| 105 } | |
| 106 | |
| 107 void DriveWebAppsRegistry::GetWebAppsForFile( | |
| 108 const base::FilePath& file, | |
| 109 const std::string& mime_type, | |
| 110 ScopedVector<DriveWebAppInfo>* apps) { | |
| 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 112 | |
| 113 SelectorWebAppList result_map; | |
| 114 if (!file.empty()) { | |
| 115 base::FilePath::StringType extension = file.Extension(); | |
| 116 if (extension.size() < 2) | |
| 117 return; | |
| 118 | |
| 119 extension = extension.substr(1); | |
| 120 if (!extension.empty()) | |
| 121 FindWebAppsForSelector(extension, webapp_extension_map_, &result_map); | |
| 122 } | |
| 123 | |
| 124 if (!mime_type.empty()) | |
| 125 FindWebAppsForSelector(mime_type, webapp_mimetypes_map_, &result_map); | |
| 126 | |
| 127 // Insert found web apps into |apps|, but skip duplicate results. | |
| 128 std::set<std::string> inserted_app_ids; | |
| 129 for (SelectorWebAppList::const_iterator it = result_map.begin(); | |
| 130 it != result_map.end(); ++it) { | |
| 131 if (inserted_app_ids.find(it->second->app_id) == inserted_app_ids.end()) { | |
| 132 inserted_app_ids.insert(it->second->app_id); | |
| 133 apps->push_back(it->second); | |
| 134 } | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 void DriveWebAppsRegistry::Update() { | |
| 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 140 | |
| 141 scheduler_->GetAppList( | |
| 142 base::Bind(&DriveWebAppsRegistry::UpdateAfterGetAppList, | |
| 143 weak_ptr_factory_.GetWeakPtr())); | |
| 144 } | |
| 145 | |
| 146 void DriveWebAppsRegistry::UpdateAfterGetAppList( | |
| 147 google_apis::GDataErrorCode gdata_error, | |
| 148 scoped_ptr<google_apis::AppList> app_list) { | |
| 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 150 | |
| 151 FileError error = util::GDataToFileError(gdata_error); | |
| 152 if (error != FILE_ERROR_OK) { | |
| 153 // Failed to fetch the data from the server. We can do nothing here. | |
| 154 return; | |
| 155 } | |
| 156 | |
| 157 DCHECK(app_list); | |
| 158 | |
| 159 url_to_name_map_.clear(); | |
| 160 STLDeleteValues(&webapp_extension_map_); | |
| 161 STLDeleteValues(&webapp_mimetypes_map_); | |
| 162 for (size_t i = 0; i < app_list->items().size(); ++i) { | |
| 163 const google_apis::AppResource& app = *app_list->items()[i]; | |
| 164 if (app.product_url().is_empty()) | |
| 165 continue; | |
| 166 | |
| 167 google_apis::InstalledApp::IconList app_icons; | |
| 168 google_apis::InstalledApp::IconList document_icons; | |
| 169 for (size_t j = 0; j < app.icons().size(); ++j) { | |
| 170 const google_apis::DriveAppIcon& icon = *app.icons()[j]; | |
| 171 if (icon.icon_url().is_empty()) | |
| 172 continue; | |
| 173 if (icon.category() == google_apis::DriveAppIcon::APPLICATION) | |
| 174 app_icons.push_back(std::make_pair(icon.icon_side_length(), | |
| 175 icon.icon_url())); | |
| 176 if (icon.category() == google_apis::DriveAppIcon::DOCUMENT) | |
| 177 document_icons.push_back(std::make_pair(icon.icon_side_length(), | |
| 178 icon.icon_url())); | |
| 179 } | |
| 180 std::sort(app_icons.begin(), app_icons.end(), SortBySize); | |
| 181 std::sort(document_icons.begin(), document_icons.end(), SortBySize); | |
| 182 | |
| 183 url_to_name_map_.insert( | |
| 184 std::make_pair(app.product_url(), app.name())); | |
| 185 AddAppSelectorList(app.product_url(), | |
| 186 app_icons, | |
| 187 document_icons, | |
| 188 app.object_type(), | |
| 189 app.application_id(), | |
| 190 true, // primary | |
| 191 app.primary_mimetypes(), | |
| 192 &webapp_mimetypes_map_); | |
| 193 AddAppSelectorList(app.product_url(), | |
| 194 app_icons, | |
| 195 document_icons, | |
| 196 app.object_type(), | |
| 197 app.application_id(), | |
| 198 false, // primary | |
| 199 app.secondary_mimetypes(), | |
| 200 &webapp_mimetypes_map_); | |
| 201 AddAppSelectorList(app.product_url(), | |
| 202 app_icons, | |
| 203 document_icons, | |
| 204 app.object_type(), | |
| 205 app.application_id(), | |
| 206 true, // primary | |
| 207 app.primary_file_extensions(), | |
| 208 &webapp_extension_map_); | |
| 209 AddAppSelectorList(app.product_url(), | |
| 210 app_icons, | |
| 211 document_icons, | |
| 212 app.object_type(), | |
| 213 app.application_id(), | |
| 214 false, // primary | |
| 215 app.secondary_file_extensions(), | |
| 216 &webapp_extension_map_); | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 // static. | |
| 221 void DriveWebAppsRegistry::AddAppSelectorList( | |
| 222 const GURL& product_link, | |
| 223 const google_apis::InstalledApp::IconList& app_icons, | |
| 224 const google_apis::InstalledApp::IconList& document_icons, | |
| 225 const std::string& object_type, | |
| 226 const std::string& app_id, | |
| 227 bool is_primary_selector, | |
| 228 const ScopedVector<std::string>& selectors, | |
| 229 WebAppFileSelectorMap* map) { | |
| 230 for (ScopedVector<std::string>::const_iterator it = selectors.begin(); | |
| 231 it != selectors.end(); ++it) { | |
| 232 std::string* value = *it; | |
| 233 map->insert(std::make_pair( | |
| 234 *value, new WebAppFileSelector(product_link, | |
| 235 app_icons, | |
| 236 document_icons, | |
| 237 UTF8ToUTF16(object_type), | |
| 238 app_id, | |
| 239 is_primary_selector))); | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 void DriveWebAppsRegistry::FindWebAppsForSelector( | |
| 244 const std::string& file_selector, | |
| 245 const WebAppFileSelectorMap& map, | |
| 246 SelectorWebAppList* apps) { | |
| 247 for (WebAppFileSelectorMap::const_iterator it = map.find(file_selector); | |
| 248 it != map.end() && it->first == file_selector; ++it) { | |
| 249 const WebAppFileSelector* web_app = it->second; | |
| 250 std::map<GURL, std::string>::const_iterator product_iter = | |
| 251 url_to_name_map_.find(web_app->product_link); | |
| 252 if (product_iter == url_to_name_map_.end()) { | |
| 253 NOTREACHED(); | |
| 254 continue; | |
| 255 } | |
| 256 | |
| 257 std::string web_store_id = GetWebStoreIdFromUrl(web_app->product_link); | |
| 258 if (web_store_id.empty()) | |
| 259 continue; | |
| 260 | |
| 261 if (apps->find(web_app) != apps->end()) | |
| 262 continue; | |
| 263 | |
| 264 apps->insert(std::make_pair( | |
| 265 web_app, | |
| 266 new DriveWebAppInfo(web_app->app_id, | |
| 267 web_app->app_icons, | |
| 268 web_app->document_icons, | |
| 269 web_store_id, | |
| 270 UTF8ToUTF16(product_iter->second), // app name. | |
| 271 web_app->object_type, | |
| 272 web_app->is_primary_selector))); | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 } // namespace drive | |
| OLD | NEW |