| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/search_engines/template_url_model.h" | 5 #include "chrome/browser/search_engines/template_url_model.h" |
| 6 | 6 |
| 7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/environment.h" | 9 #include "base/environment.h" |
| 10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 | 87 |
| 88 TemplateURLModel::~TemplateURLModel() { | 88 TemplateURLModel::~TemplateURLModel() { |
| 89 if (load_handle_) { | 89 if (load_handle_) { |
| 90 DCHECK(service_.get()); | 90 DCHECK(service_.get()); |
| 91 service_->CancelRequest(load_handle_); | 91 service_->CancelRequest(load_handle_); |
| 92 } | 92 } |
| 93 | 93 |
| 94 STLDeleteElements(&template_urls_); | 94 STLDeleteElements(&template_urls_); |
| 95 } | 95 } |
| 96 | 96 |
| 97 void TemplateURLModel::Init(const Initializer* initializers, | |
| 98 int num_initializers) { | |
| 99 // Register for notifications. | |
| 100 if (profile_) { | |
| 101 // TODO(sky): bug 1166191. The keywords should be moved into the history | |
| 102 // db, which will mean we no longer need this notification and the history | |
| 103 // backend can handle automatically adding the search terms as the user | |
| 104 // navigates. | |
| 105 registrar_.Add(this, NotificationType::HISTORY_URL_VISITED, | |
| 106 Source<Profile>(profile_->GetOriginalProfile())); | |
| 107 } | |
| 108 registrar_.Add(this, NotificationType::GOOGLE_URL_UPDATED, | |
| 109 NotificationService::AllSources()); | |
| 110 | |
| 111 // Add specific initializers, if any. | |
| 112 for (int i(0); i < num_initializers; ++i) { | |
| 113 DCHECK(initializers[i].keyword); | |
| 114 DCHECK(initializers[i].url); | |
| 115 DCHECK(initializers[i].content); | |
| 116 | |
| 117 size_t template_position = | |
| 118 std::string(initializers[i].url).find(kTemplateParameter); | |
| 119 DCHECK(template_position != std::wstring::npos); | |
| 120 std::string osd_url(initializers[i].url); | |
| 121 osd_url.replace(template_position, arraysize(kTemplateParameter) - 1, | |
| 122 kSearchTermParameter); | |
| 123 | |
| 124 // TemplateURLModel ends up owning the TemplateURL, don't try and free it. | |
| 125 TemplateURL* template_url = new TemplateURL(); | |
| 126 template_url->set_keyword(initializers[i].keyword); | |
| 127 template_url->set_short_name(initializers[i].content); | |
| 128 template_url->SetURL(osd_url, 0, 0); | |
| 129 Add(template_url); | |
| 130 } | |
| 131 | |
| 132 // Request a server check for the correct Google URL if Google is the default | |
| 133 // search engine, not in headless mode and not in Chrome Frame. | |
| 134 const TemplateURL* default_provider = GetDefaultSearchProvider(); | |
| 135 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
| 136 if (default_provider && !env->HasVar(env_vars::kHeadless) && | |
| 137 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) { | |
| 138 const TemplateURLRef* default_provider_ref = default_provider->url(); | |
| 139 if (default_provider_ref && default_provider_ref->HasGoogleBaseURLs()) | |
| 140 GoogleURLTracker::RequestServerCheck(); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 // static | 97 // static |
| 145 std::wstring TemplateURLModel::GenerateKeyword(const GURL& url, | 98 std::wstring TemplateURLModel::GenerateKeyword(const GURL& url, |
| 146 bool autodetected) { | 99 bool autodetected) { |
| 147 // Don't autogenerate keywords for referrers that are the result of a form | 100 // Don't autogenerate keywords for referrers that are the result of a form |
| 148 // submission (TODO: right now we approximate this by checking for the URL | 101 // submission (TODO: right now we approximate this by checking for the URL |
| 149 // having a query, but we should replace this with a call to WebCore to see if | 102 // having a query, but we should replace this with a call to WebCore to see if |
| 150 // the originating page was actually a form submission), anything other than | 103 // the originating page was actually a form submission), anything other than |
| 151 // http, or referrers with a path. | 104 // http, or referrers with a path. |
| 152 // | 105 // |
| 153 // If we relax the path constraint, we need to be sure to sanitize the path | 106 // If we relax the path constraint, we need to be sure to sanitize the path |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 | 237 |
| 285 if (service_.get()) | 238 if (service_.get()) |
| 286 service_->AddKeyword(*template_url); | 239 service_->AddKeyword(*template_url); |
| 287 | 240 |
| 288 if (loaded_) { | 241 if (loaded_) { |
| 289 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, | 242 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, |
| 290 OnTemplateURLModelChanged()); | 243 OnTemplateURLModelChanged()); |
| 291 } | 244 } |
| 292 } | 245 } |
| 293 | 246 |
| 294 void TemplateURLModel::AddToMaps(const TemplateURL* template_url) { | |
| 295 if (!template_url->keyword().empty()) | |
| 296 keyword_to_template_map_[template_url->keyword()] = template_url; | |
| 297 | |
| 298 const GURL url(GenerateSearchURL(template_url)); | |
| 299 if (url.is_valid() && url.has_host()) | |
| 300 host_to_urls_map_[url.host()].insert(template_url); | |
| 301 } | |
| 302 | |
| 303 void TemplateURLModel::Remove(const TemplateURL* template_url) { | 247 void TemplateURLModel::Remove(const TemplateURL* template_url) { |
| 304 TemplateURLVector::iterator i = find(template_urls_.begin(), | 248 TemplateURLVector::iterator i = find(template_urls_.begin(), |
| 305 template_urls_.end(), | 249 template_urls_.end(), |
| 306 template_url); | 250 template_url); |
| 307 if (i == template_urls_.end()) | 251 if (i == template_urls_.end()) |
| 308 return; | 252 return; |
| 309 | 253 |
| 310 if (template_url == default_search_provider_) { | 254 if (template_url == default_search_provider_) { |
| 311 // Should never delete the default search provider. | 255 // Should never delete the default search provider. |
| 312 NOTREACHED(); | 256 NOTREACHED(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 330 HistoryService* history = | 274 HistoryService* history = |
| 331 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | 275 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); |
| 332 if (history) | 276 if (history) |
| 333 history->DeleteAllSearchTermsForKeyword(template_url->id()); | 277 history->DeleteAllSearchTermsForKeyword(template_url->id()); |
| 334 } | 278 } |
| 335 | 279 |
| 336 // We own the TemplateURL and need to delete it. | 280 // We own the TemplateURL and need to delete it. |
| 337 delete template_url; | 281 delete template_url; |
| 338 } | 282 } |
| 339 | 283 |
| 284 void TemplateURLModel::RemoveAutoGeneratedBetween(Time created_after, |
| 285 Time created_before) { |
| 286 for (size_t i = 0; i < template_urls_.size();) { |
| 287 if (template_urls_[i]->date_created() >= created_after && |
| 288 (created_before.is_null() || |
| 289 template_urls_[i]->date_created() < created_before) && |
| 290 CanReplace(template_urls_[i])) { |
| 291 Remove(template_urls_[i]); |
| 292 } else { |
| 293 ++i; |
| 294 } |
| 295 } |
| 296 } |
| 297 |
| 340 void TemplateURLModel::Replace(const TemplateURL* existing_turl, | 298 void TemplateURLModel::Replace(const TemplateURL* existing_turl, |
| 341 TemplateURL* new_turl) { | 299 TemplateURL* new_turl) { |
| 342 DCHECK(existing_turl && new_turl); | 300 DCHECK(existing_turl && new_turl); |
| 343 | 301 |
| 344 TemplateURLVector::iterator i = find(template_urls_.begin(), | 302 TemplateURLVector::iterator i = find(template_urls_.begin(), |
| 345 template_urls_.end(), | 303 template_urls_.end(), |
| 346 existing_turl); | 304 existing_turl); |
| 347 DCHECK(i != template_urls_.end()); | 305 DCHECK(i != template_urls_.end()); |
| 348 RemoveFromMaps(existing_turl); | 306 RemoveFromMaps(existing_turl); |
| 349 template_urls_.erase(i); | 307 template_urls_.erase(i); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 360 SetDefaultSearchProvider(new_turl); | 318 SetDefaultSearchProvider(new_turl); |
| 361 | 319 |
| 362 if (loaded_) { | 320 if (loaded_) { |
| 363 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, | 321 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, |
| 364 OnTemplateURLModelChanged()); | 322 OnTemplateURLModelChanged()); |
| 365 } | 323 } |
| 366 | 324 |
| 367 delete existing_turl; | 325 delete existing_turl; |
| 368 } | 326 } |
| 369 | 327 |
| 370 void TemplateURLModel::RemoveAutoGeneratedBetween(Time created_after, | |
| 371 Time created_before) { | |
| 372 for (size_t i = 0; i < template_urls_.size();) { | |
| 373 if (template_urls_[i]->date_created() >= created_after && | |
| 374 (created_before.is_null() || | |
| 375 template_urls_[i]->date_created() < created_before) && | |
| 376 CanReplace(template_urls_[i])) { | |
| 377 Remove(template_urls_[i]); | |
| 378 } else { | |
| 379 ++i; | |
| 380 } | |
| 381 } | |
| 382 } | |
| 383 | |
| 384 void TemplateURLModel::RemoveAutoGeneratedSince(Time created_after) { | 328 void TemplateURLModel::RemoveAutoGeneratedSince(Time created_after) { |
| 385 RemoveAutoGeneratedBetween(created_after, Time()); | 329 RemoveAutoGeneratedBetween(created_after, Time()); |
| 386 } | 330 } |
| 387 | 331 |
| 388 void TemplateURLModel::SetKeywordSearchTermsForURL(const TemplateURL* t_url, | 332 void TemplateURLModel::RegisterExtensionKeyword(Extension* extension) { |
| 389 const GURL& url, | 333 // TODO(mpcomplete): disable the keyword when the extension is disabled. |
| 390 const std::wstring& term) { | 334 if (extension->omnibox_keyword().empty()) |
| 391 HistoryService* history = profile_ ? | |
| 392 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; | |
| 393 if (!history) | |
| 394 return; | 335 return; |
| 395 history->SetKeywordSearchTermsForURL(url, t_url->id(), | |
| 396 WideToUTF16Hack(term)); | |
| 397 } | |
| 398 | 336 |
| 399 void TemplateURLModel::RemoveFromMaps(const TemplateURL* template_url) { | 337 Load(); |
| 400 if (!template_url->keyword().empty()) { | 338 if (!loaded_) { |
| 401 keyword_to_template_map_.erase(template_url->keyword()); | 339 pending_extension_ids_.push_back(extension->id()); |
| 340 return; |
| 402 } | 341 } |
| 403 | 342 |
| 404 const GURL url(GenerateSearchURL(template_url)); | 343 const TemplateURL* existing_url = GetTemplateURLForExtension(extension); |
| 405 if (url.is_valid() && url.has_host()) { | 344 std::wstring keyword = UTF8ToWide(extension->omnibox_keyword()); |
| 406 const std::string host(url.host()); | 345 |
| 407 DCHECK(host_to_urls_map_.find(host) != host_to_urls_map_.end()); | 346 TemplateURL* template_url = new TemplateURL; |
| 408 TemplateURLSet& urls = host_to_urls_map_[host]; | 347 template_url->set_short_name(UTF8ToWide(extension->name())); |
| 409 DCHECK(urls.find(template_url) != urls.end()); | 348 template_url->set_keyword(keyword); |
| 410 urls.erase(urls.find(template_url)); | 349 // This URL is not actually used for navigation. It holds the extension's |
| 411 if (urls.empty()) | 350 // ID, as well as forcing the TemplateURL to be treated as a search keyword. |
| 412 host_to_urls_map_.erase(host_to_urls_map_.find(host)); | 351 template_url->SetURL( |
| 352 std::string(chrome::kExtensionScheme) + "://" + |
| 353 extension->id() + "/?q={searchTerms}", 0, 0); |
| 354 template_url->set_safe_for_autoreplace(false); |
| 355 |
| 356 if (existing_url) { |
| 357 // TODO(mpcomplete): only replace if the user hasn't changed the keyword. |
| 358 // (We don't have UI for that yet). |
| 359 Replace(existing_url, template_url); |
| 360 } else { |
| 361 Add(template_url); |
| 413 } | 362 } |
| 414 } | 363 } |
| 415 | 364 |
| 416 void TemplateURLModel::RemoveFromMapsByPointer( | 365 void TemplateURLModel::UnregisterExtensionKeyword(Extension* extension) { |
| 417 const TemplateURL* template_url) { | 366 const TemplateURL* url = GetTemplateURLForExtension(extension); |
| 418 DCHECK(template_url); | 367 if (url) |
| 419 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); | 368 Remove(url); |
| 420 i != keyword_to_template_map_.end(); ++i) { | 369 } |
| 421 if (i->second == template_url) { | 370 |
| 422 keyword_to_template_map_.erase(i); | 371 const TemplateURL* TemplateURLModel::GetTemplateURLForExtension( |
| 423 // A given TemplateURL only occurs once in the map. As soon as we find the | 372 Extension* extension) const { |
| 424 // entry, stop. | 373 for (TemplateURLVector::const_iterator i = template_urls_.begin(); |
| 425 break; | 374 i != template_urls_.end(); ++i) { |
| 426 } | 375 if ((*i)->IsExtensionKeyword() && (*i)->url()->GetHost() == extension->id()) |
| 376 return *i; |
| 427 } | 377 } |
| 428 | 378 |
| 429 for (HostToURLsMap::iterator i = host_to_urls_map_.begin(); | 379 return NULL; |
| 430 i != host_to_urls_map_.end(); ++i) { | |
| 431 TemplateURLSet::iterator url_set_iterator = i->second.find(template_url); | |
| 432 if (url_set_iterator != i->second.end()) { | |
| 433 i->second.erase(url_set_iterator); | |
| 434 if (i->second.empty()) | |
| 435 host_to_urls_map_.erase(i); | |
| 436 // A given TemplateURL only occurs once in the map. As soon as we find the | |
| 437 // entry, stop. | |
| 438 return; | |
| 439 } | |
| 440 } | |
| 441 } | |
| 442 | |
| 443 void TemplateURLModel::SetTemplateURLs( | |
| 444 const std::vector<const TemplateURL*>& urls) { | |
| 445 // Add mappings for the new items. | |
| 446 for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end(); | |
| 447 ++i) { | |
| 448 next_id_ = std::max(next_id_, (*i)->id()); | |
| 449 AddToMaps(*i); | |
| 450 template_urls_.push_back(*i); | |
| 451 } | |
| 452 } | 380 } |
| 453 | 381 |
| 454 std::vector<const TemplateURL*> TemplateURLModel::GetTemplateURLs() const { | 382 std::vector<const TemplateURL*> TemplateURLModel::GetTemplateURLs() const { |
| 455 return template_urls_; | 383 return template_urls_; |
| 456 } | 384 } |
| 457 | 385 |
| 458 void TemplateURLModel::IncrementUsageCount(const TemplateURL* url) { | 386 void TemplateURLModel::IncrementUsageCount(const TemplateURL* url) { |
| 459 DCHECK(url && find(template_urls_.begin(), template_urls_.end(), url) != | 387 DCHECK(url && find(template_urls_.begin(), template_urls_.end(), url) != |
| 460 template_urls_.end()); | 388 template_urls_.end()); |
| 461 const_cast<TemplateURL*>(url)->set_usage_count(url->usage_count() + 1); | 389 const_cast<TemplateURL*>(url)->set_usage_count(url->usage_count() + 1); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 else | 632 else |
| 705 UpdateKeywordSearchTermsForURL(*visit_details.ptr()); | 633 UpdateKeywordSearchTermsForURL(*visit_details.ptr()); |
| 706 } else if (type == NotificationType::GOOGLE_URL_UPDATED) { | 634 } else if (type == NotificationType::GOOGLE_URL_UPDATED) { |
| 707 if (loaded_) | 635 if (loaded_) |
| 708 GoogleBaseURLChanged(); | 636 GoogleBaseURLChanged(); |
| 709 } else { | 637 } else { |
| 710 NOTREACHED(); | 638 NOTREACHED(); |
| 711 } | 639 } |
| 712 } | 640 } |
| 713 | 641 |
| 642 void TemplateURLModel::SetKeywordSearchTermsForURL(const TemplateURL* t_url, |
| 643 const GURL& url, |
| 644 const std::wstring& term) { |
| 645 HistoryService* history = profile_ ? |
| 646 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; |
| 647 if (!history) |
| 648 return; |
| 649 history->SetKeywordSearchTermsForURL(url, t_url->id(), |
| 650 WideToUTF16Hack(term)); |
| 651 } |
| 652 |
| 653 void TemplateURLModel::Init(const Initializer* initializers, |
| 654 int num_initializers) { |
| 655 // Register for notifications. |
| 656 if (profile_) { |
| 657 // TODO(sky): bug 1166191. The keywords should be moved into the history |
| 658 // db, which will mean we no longer need this notification and the history |
| 659 // backend can handle automatically adding the search terms as the user |
| 660 // navigates. |
| 661 registrar_.Add(this, NotificationType::HISTORY_URL_VISITED, |
| 662 Source<Profile>(profile_->GetOriginalProfile())); |
| 663 } |
| 664 registrar_.Add(this, NotificationType::GOOGLE_URL_UPDATED, |
| 665 NotificationService::AllSources()); |
| 666 |
| 667 // Add specific initializers, if any. |
| 668 for (int i(0); i < num_initializers; ++i) { |
| 669 DCHECK(initializers[i].keyword); |
| 670 DCHECK(initializers[i].url); |
| 671 DCHECK(initializers[i].content); |
| 672 |
| 673 size_t template_position = |
| 674 std::string(initializers[i].url).find(kTemplateParameter); |
| 675 DCHECK(template_position != std::wstring::npos); |
| 676 std::string osd_url(initializers[i].url); |
| 677 osd_url.replace(template_position, arraysize(kTemplateParameter) - 1, |
| 678 kSearchTermParameter); |
| 679 |
| 680 // TemplateURLModel ends up owning the TemplateURL, don't try and free it. |
| 681 TemplateURL* template_url = new TemplateURL(); |
| 682 template_url->set_keyword(initializers[i].keyword); |
| 683 template_url->set_short_name(initializers[i].content); |
| 684 template_url->SetURL(osd_url, 0, 0); |
| 685 Add(template_url); |
| 686 } |
| 687 |
| 688 // Request a server check for the correct Google URL if Google is the default |
| 689 // search engine, not in headless mode and not in Chrome Frame. |
| 690 const TemplateURL* default_provider = GetDefaultSearchProvider(); |
| 691 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 692 if (default_provider && !env->HasVar(env_vars::kHeadless) && |
| 693 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) { |
| 694 const TemplateURLRef* default_provider_ref = default_provider->url(); |
| 695 if (default_provider_ref && default_provider_ref->HasGoogleBaseURLs()) |
| 696 GoogleURLTracker::RequestServerCheck(); |
| 697 } |
| 698 } |
| 699 |
| 700 void TemplateURLModel::RemoveFromMaps(const TemplateURL* template_url) { |
| 701 if (!template_url->keyword().empty()) { |
| 702 keyword_to_template_map_.erase(template_url->keyword()); |
| 703 } |
| 704 |
| 705 const GURL url(GenerateSearchURL(template_url)); |
| 706 if (url.is_valid() && url.has_host()) { |
| 707 const std::string host(url.host()); |
| 708 DCHECK(host_to_urls_map_.find(host) != host_to_urls_map_.end()); |
| 709 TemplateURLSet& urls = host_to_urls_map_[host]; |
| 710 DCHECK(urls.find(template_url) != urls.end()); |
| 711 urls.erase(urls.find(template_url)); |
| 712 if (urls.empty()) |
| 713 host_to_urls_map_.erase(host_to_urls_map_.find(host)); |
| 714 } |
| 715 } |
| 716 |
| 717 void TemplateURLModel::RemoveFromMapsByPointer( |
| 718 const TemplateURL* template_url) { |
| 719 DCHECK(template_url); |
| 720 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); |
| 721 i != keyword_to_template_map_.end(); ++i) { |
| 722 if (i->second == template_url) { |
| 723 keyword_to_template_map_.erase(i); |
| 724 // A given TemplateURL only occurs once in the map. As soon as we find the |
| 725 // entry, stop. |
| 726 break; |
| 727 } |
| 728 } |
| 729 |
| 730 for (HostToURLsMap::iterator i = host_to_urls_map_.begin(); |
| 731 i != host_to_urls_map_.end(); ++i) { |
| 732 TemplateURLSet::iterator url_set_iterator = i->second.find(template_url); |
| 733 if (url_set_iterator != i->second.end()) { |
| 734 i->second.erase(url_set_iterator); |
| 735 if (i->second.empty()) |
| 736 host_to_urls_map_.erase(i); |
| 737 // A given TemplateURL only occurs once in the map. As soon as we find the |
| 738 // entry, stop. |
| 739 return; |
| 740 } |
| 741 } |
| 742 } |
| 743 |
| 744 void TemplateURLModel::AddToMaps(const TemplateURL* template_url) { |
| 745 if (!template_url->keyword().empty()) |
| 746 keyword_to_template_map_[template_url->keyword()] = template_url; |
| 747 |
| 748 const GURL url(GenerateSearchURL(template_url)); |
| 749 if (url.is_valid() && url.has_host()) |
| 750 host_to_urls_map_[url.host()].insert(template_url); |
| 751 } |
| 752 |
| 753 void TemplateURLModel::SetTemplateURLs( |
| 754 const std::vector<const TemplateURL*>& urls) { |
| 755 // Add mappings for the new items. |
| 756 for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end(); |
| 757 ++i) { |
| 758 next_id_ = std::max(next_id_, (*i)->id()); |
| 759 AddToMaps(*i); |
| 760 template_urls_.push_back(*i); |
| 761 } |
| 762 } |
| 763 |
| 714 void TemplateURLModel::DeleteGeneratedKeywordsMatchingHost( | 764 void TemplateURLModel::DeleteGeneratedKeywordsMatchingHost( |
| 715 const std::wstring& host) { | 765 const std::wstring& host) { |
| 716 const std::wstring host_slash = host + L"/"; | 766 const std::wstring host_slash = host + L"/"; |
| 717 // Iterate backwards as we may end up removing multiple entries. | 767 // Iterate backwards as we may end up removing multiple entries. |
| 718 for (int i = static_cast<int>(template_urls_.size()) - 1; i >= 0; --i) { | 768 for (int i = static_cast<int>(template_urls_.size()) - 1; i >= 0; --i) { |
| 719 if (CanReplace(template_urls_[i]) && | 769 if (CanReplace(template_urls_[i]) && |
| 720 (template_urls_[i]->keyword() == host || | 770 (template_urls_[i]->keyword() == host || |
| 721 template_urls_[i]->keyword().compare(0, host_slash.length(), | 771 template_urls_[i]->keyword().compare(0, host_slash.length(), |
| 722 host_slash) == 0)) { | 772 host_slash) == 0)) { |
| 723 Remove(template_urls_[i]); | 773 Remove(template_urls_[i]); |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 AddToMaps(t_url); | 1112 AddToMaps(t_url); |
| 1063 something_changed = true; | 1113 something_changed = true; |
| 1064 } | 1114 } |
| 1065 } | 1115 } |
| 1066 | 1116 |
| 1067 if (something_changed && loaded_) { | 1117 if (something_changed && loaded_) { |
| 1068 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, | 1118 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, |
| 1069 OnTemplateURLModelChanged()); | 1119 OnTemplateURLModelChanged()); |
| 1070 } | 1120 } |
| 1071 } | 1121 } |
| 1072 | |
| 1073 void TemplateURLModel::RegisterExtensionKeyword(Extension* extension) { | |
| 1074 // TODO(mpcomplete): disable the keyword when the extension is disabled. | |
| 1075 if (extension->omnibox_keyword().empty()) | |
| 1076 return; | |
| 1077 | |
| 1078 Load(); | |
| 1079 if (!loaded_) { | |
| 1080 pending_extension_ids_.push_back(extension->id()); | |
| 1081 return; | |
| 1082 } | |
| 1083 | |
| 1084 const TemplateURL* existing_url = GetTemplateURLForExtension(extension); | |
| 1085 std::wstring keyword = UTF8ToWide(extension->omnibox_keyword()); | |
| 1086 | |
| 1087 TemplateURL* template_url = new TemplateURL; | |
| 1088 template_url->set_short_name(UTF8ToWide(extension->name())); | |
| 1089 template_url->set_keyword(keyword); | |
| 1090 // This URL is not actually used for navigation. It holds the extension's | |
| 1091 // ID, as well as forcing the TemplateURL to be treated as a search keyword. | |
| 1092 template_url->SetURL( | |
| 1093 std::string(chrome::kExtensionScheme) + "://" + | |
| 1094 extension->id() + "/?q={searchTerms}", 0, 0); | |
| 1095 template_url->set_safe_for_autoreplace(false); | |
| 1096 | |
| 1097 if (existing_url) { | |
| 1098 // TODO(mpcomplete): only replace if the user hasn't changed the keyword. | |
| 1099 // (We don't have UI for that yet). | |
| 1100 Replace(existing_url, template_url); | |
| 1101 } else { | |
| 1102 Add(template_url); | |
| 1103 } | |
| 1104 } | |
| 1105 | |
| 1106 void TemplateURLModel::UnregisterExtensionKeyword(Extension* extension) { | |
| 1107 const TemplateURL* url = GetTemplateURLForExtension(extension); | |
| 1108 if (url) | |
| 1109 Remove(url); | |
| 1110 } | |
| 1111 | |
| 1112 const TemplateURL* TemplateURLModel::GetTemplateURLForExtension( | |
| 1113 Extension* extension) const { | |
| 1114 for (TemplateURLVector::const_iterator i = template_urls_.begin(); | |
| 1115 i != template_urls_.end(); ++i) { | |
| 1116 if ((*i)->IsExtensionKeyword() && (*i)->url()->GetHost() == extension->id()) | |
| 1117 return *i; | |
| 1118 } | |
| 1119 | |
| 1120 return NULL; | |
| 1121 } | |
| OLD | NEW |