• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/ui/search_engines/edit_search_engine_controller.h"
6 
7 #include "base/string_util.h"
8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/metrics/user_metrics.h"
10 #include "chrome/browser/net/url_fixer_upper.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/search_engines/template_url.h"
13 #include "chrome/browser/search_engines/template_url_model.h"
14 #include "googleurl/src/gurl.h"
15 
EditSearchEngineController(const TemplateURL * template_url,EditSearchEngineControllerDelegate * edit_keyword_delegate,Profile * profile)16 EditSearchEngineController::EditSearchEngineController(
17     const TemplateURL* template_url,
18     EditSearchEngineControllerDelegate* edit_keyword_delegate,
19     Profile* profile)
20     : template_url_(template_url),
21       edit_keyword_delegate_(edit_keyword_delegate),
22       profile_(profile) {
23   DCHECK(profile_);
24 }
25 
IsTitleValid(const string16 & title_input) const26 bool EditSearchEngineController::IsTitleValid(
27     const string16& title_input) const {
28   return !CollapseWhitespace(title_input, true).empty();
29 }
30 
IsURLValid(const std::string & url_input) const31 bool EditSearchEngineController::IsURLValid(
32     const std::string& url_input) const {
33   std::string url = GetFixedUpURL(url_input);
34   if (url.empty())
35     return false;
36 
37   // Use TemplateURLRef to extract the search placeholder.
38   TemplateURLRef template_ref(url, 0, 0);
39   if (!template_ref.IsValid())
40     return false;
41 
42   if (!template_ref.SupportsReplacement()) {
43     // If this is the default search engine, there must be a search term
44     // placeholder.
45     if (template_url_ ==
46         profile_->GetTemplateURLModel()->GetDefaultSearchProvider())
47       return false;
48     return GURL(url).is_valid();
49   }
50 
51   // If the url has a search term, replace it with a random string and make
52   // sure the resulting URL is valid. We don't check the validity of the url
53   // with the search term as that is not necessarily valid.
54   return GURL(template_ref.ReplaceSearchTerms(TemplateURL(), ASCIIToUTF16("a"),
55       TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())).is_valid();
56 }
57 
IsKeywordValid(const string16 & keyword_input) const58 bool EditSearchEngineController::IsKeywordValid(
59     const string16& keyword_input) const {
60   string16 keyword_input_trimmed(CollapseWhitespace(keyword_input, true));
61   if (keyword_input_trimmed.empty())
62     return false;  // Do not allow empty keyword.
63   const TemplateURL* turl_with_keyword =
64       profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(
65           keyword_input_trimmed);
66   return (turl_with_keyword == NULL || turl_with_keyword == template_url_);
67 }
68 
AcceptAddOrEdit(const string16 & title_input,const string16 & keyword_input,const std::string & url_input)69 void EditSearchEngineController::AcceptAddOrEdit(
70     const string16& title_input,
71     const string16& keyword_input,
72     const std::string& url_input) {
73   std::string url_string = GetFixedUpURL(url_input);
74   DCHECK(!url_string.empty());
75 
76   const TemplateURL* existing =
77       profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(
78           keyword_input);
79   if (existing &&
80       (!edit_keyword_delegate_ || existing != template_url_)) {
81     // An entry may have been added with the same keyword string while the
82     // user edited the dialog, either automatically or by the user (if we're
83     // confirming a JS addition, they could have the Options dialog open at the
84     // same time). If so, just ignore this add.
85     // TODO(pamg): Really, we should modify the entry so this later one
86     // overwrites it. But we don't expect this case to be common.
87     CleanUpCancelledAdd();
88     return;
89   }
90 
91   if (!edit_keyword_delegate_) {
92     // Confiming an entry we got from JS. We have a template_url_, but it
93     // hasn't yet been added to the model.
94     DCHECK(template_url_);
95     // const_cast is ugly, but this is the same thing the TemplateURLModel
96     // does in a similar situation (updating an existing TemplateURL with
97     // data from a new one).
98     TemplateURL* modifiable_url = const_cast<TemplateURL*>(template_url_);
99     modifiable_url->set_short_name(title_input);
100     modifiable_url->set_keyword(keyword_input);
101     modifiable_url->SetURL(url_string, 0, 0);
102     // TemplateURLModel takes ownership of template_url_.
103     profile_->GetTemplateURLModel()->Add(modifiable_url);
104     UserMetrics::RecordAction(UserMetricsAction("KeywordEditor_AddKeywordJS"),
105                               profile_);
106   } else {
107     // Adding or modifying an entry via the Delegate.
108     edit_keyword_delegate_->OnEditedKeyword(template_url_,
109                                             title_input,
110                                             keyword_input,
111                                             url_string);
112   }
113 }
114 
CleanUpCancelledAdd()115 void EditSearchEngineController::CleanUpCancelledAdd() {
116   if (!edit_keyword_delegate_ && template_url_) {
117     // When we have no Delegate, we know that the template_url_ hasn't yet been
118     // added to the model, so we need to clean it up.
119     delete template_url_;
120     template_url_ = NULL;
121   }
122 }
123 
GetFixedUpURL(const std::string & url_input) const124 std::string EditSearchEngineController::GetFixedUpURL(
125     const std::string& url_input) const {
126   std::string url;
127   TrimWhitespace(TemplateURLRef::DisplayURLToURLRef(UTF8ToUTF16(url_input)),
128                  TRIM_ALL, &url);
129   if (url.empty())
130     return url;
131 
132   // Parse the string as a URL to determine the scheme. If we need to, add the
133   // scheme. As the scheme may be expanded (as happens with {google:baseURL})
134   // we need to replace the search terms before testing for the scheme.
135   TemplateURL t_url;
136   t_url.SetURL(url, 0, 0);
137   std::string expanded_url =
138       t_url.url()->ReplaceSearchTerms(t_url, ASCIIToUTF16("x"), 0, string16());
139   url_parse::Parsed parts;
140   std::string scheme(
141       URLFixerUpper::SegmentURL(expanded_url, &parts));
142   if (!parts.scheme.is_valid()) {
143     scheme.append("://");
144     url.insert(0, scheme);
145   }
146 
147   return url;
148 }
149 
150