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 |