diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-17 18:29:43 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-17 18:29:43 +0000 |
commit | 57d8663235c088b31aac1cedb0a7e46b24d8ef5c (patch) | |
tree | 379cd3cb46978d65ce0123245851e473fa570bed /chrome/browser | |
parent | 95c1aac9bbd395e30fb4003d947f3f61089d6312 (diff) | |
download | chromium_src-57d8663235c088b31aac1cedb0a7e46b24d8ef5c.zip chromium_src-57d8663235c088b31aac1cedb0a7e46b24d8ef5c.tar.gz chromium_src-57d8663235c088b31aac1cedb0a7e46b24d8ef5c.tar.bz2 |
Refactor platform-independent stuff out of EditKeywordController.
Preparation for adding GTK implementation.
BUG=13326
TEST=Edit existing search engine, add new search engine, add engine by clicking on OpenSearch description file.
Review URL: http://codereview.chromium.org/125161
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18636 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/search_engines/edit_keyword_controller_base.cc | 130 | ||||
-rw-r--r-- | chrome/browser/search_engines/edit_keyword_controller_base.h | 91 | ||||
-rw-r--r-- | chrome/browser/views/edit_keyword_controller.cc | 143 | ||||
-rw-r--r-- | chrome/browser/views/edit_keyword_controller.h | 43 | ||||
-rw-r--r-- | chrome/browser/views/keyword_editor_view.cc | 11 | ||||
-rw-r--r-- | chrome/browser/views/keyword_editor_view.h | 11 |
6 files changed, 269 insertions, 160 deletions
diff --git a/chrome/browser/search_engines/edit_keyword_controller_base.cc b/chrome/browser/search_engines/edit_keyword_controller_base.cc new file mode 100644 index 0000000..8206d1d --- /dev/null +++ b/chrome/browser/search_engines/edit_keyword_controller_base.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2009 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/search_engines/edit_keyword_controller_base.h" + +#include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/net/url_fixer_upper.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/search_engines/template_url.h" +#include "chrome/browser/search_engines/template_url_model.h" + +EditKeywordControllerBase::EditKeywordControllerBase( + const TemplateURL* template_url, + Delegate* edit_keyword_delegate, + Profile* profile) + : template_url_(template_url), + edit_keyword_delegate_(edit_keyword_delegate), + profile_(profile) { + DCHECK(profile_); +} + +bool EditKeywordControllerBase::IsTitleValid() const { + return !GetTitleInput().empty(); +} + +bool EditKeywordControllerBase::IsURLValid() const { + std::wstring url = GetURL(); + if (url.empty()) + return false; + + // Use TemplateURLRef to extract the search placeholder. + TemplateURLRef template_ref(url, 0, 0); + if (!template_ref.IsValid()) + return false; + + if (!template_ref.SupportsReplacement()) + return GURL(WideToUTF16Hack(url)).is_valid(); + + // If the url has a search term, replace it with a random string and make + // sure the resulting URL is valid. We don't check the validity of the url + // with the search term as that is not necessarily valid. + return GURL(WideToUTF8(template_ref.ReplaceSearchTerms(TemplateURL(), L"a", + TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()))).is_valid(); +} + +std::wstring EditKeywordControllerBase::GetURL() const { + std::wstring url; + TrimWhitespace(TemplateURLRef::DisplayURLToURLRef(GetURLInput()), + TRIM_ALL, &url); + if (url.empty()) + return url; + + // Parse the string as a URL to determine the scheme. If we need to, add the + // scheme. As the scheme may be expanded (as happens with {google:baseURL}) + // we need to replace the search terms before testing for the scheme. + TemplateURL t_url; + t_url.SetURL(url, 0, 0); + std::wstring expanded_url = + t_url.url()->ReplaceSearchTerms(t_url, L"x", 0, std::wstring()); + url_parse::Parsed parts; + std::string scheme( + URLFixerUpper::SegmentURL(WideToUTF8(expanded_url), &parts)); + if(!parts.scheme.is_valid()) { + scheme.append("://"); + url.insert(0, UTF8ToWide(scheme)); + } + + return url; +} + +bool EditKeywordControllerBase::IsKeywordValid() const { + std::wstring keyword = GetKeywordInput(); + if (keyword.empty()) + return true; // Always allow no keyword. + const TemplateURL* turl_with_keyword = + profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword); + return (turl_with_keyword == NULL || turl_with_keyword == template_url_); +} + +void EditKeywordControllerBase::AcceptAddOrEdit() { + std::wstring url_string = GetURL(); + DCHECK(!url_string.empty()); + std::wstring keyword = GetKeywordInput(); + + const TemplateURL* existing = + profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword); + if (existing && + (!edit_keyword_delegate_ || existing != template_url_)) { + // An entry may have been added with the same keyword string while the + // user edited the dialog, either automatically or by the user (if we're + // confirming a JS addition, they could have the Options dialog open at the + // same time). If so, just ignore this add. + // TODO(pamg): Really, we should modify the entry so this later one + // overwrites it. But we don't expect this case to be common. + CleanUpCancelledAdd(); + return; + } + + if (!edit_keyword_delegate_) { + // Confiming an entry we got from JS. We have a template_url_, but it + // hasn't yet been added to the model. + DCHECK(template_url_); + // const_cast is ugly, but this is the same thing the TemplateURLModel + // does in a similar situation (updating an existing TemplateURL with + // data from a new one). + TemplateURL* modifiable_url = const_cast<TemplateURL*>(template_url_); + modifiable_url->set_short_name(GetTitleInput()); + modifiable_url->set_keyword(keyword); + modifiable_url->SetURL(url_string, 0, 0); + // TemplateURLModel takes ownership of template_url_. + profile_->GetTemplateURLModel()->Add(modifiable_url); + UserMetrics::RecordAction(L"KeywordEditor_AddKeywordJS", profile_); + } else { + // Adding or modifying an entry via the Delegate. + edit_keyword_delegate_->OnEditedKeyword(template_url_, + GetTitleInput(), + GetKeywordInput(), + url_string); + } +} + +void EditKeywordControllerBase::CleanUpCancelledAdd() { + if (!edit_keyword_delegate_ && template_url_) { + // When we have no Delegate, we know that the template_url_ hasn't yet been + // added to the model, so we need to clean it up. + delete template_url_; + template_url_ = NULL; + } +} diff --git a/chrome/browser/search_engines/edit_keyword_controller_base.h b/chrome/browser/search_engines/edit_keyword_controller_base.h new file mode 100644 index 0000000..11b3080 --- /dev/null +++ b/chrome/browser/search_engines/edit_keyword_controller_base.h @@ -0,0 +1,91 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_SEARCH_ENGINES_EDIT_KEYWORD_CONTROLLER_BASE_H_ +#define CHROME_BROWSER_SEARCH_ENGINES_EDIT_KEYWORD_CONTROLLER_BASE_H_ + +#include <string> + +class Profile; +class TemplateURL; + +// EditKeywordControllerBase provides the platform independent logic and +// interface for implementing a dialog for editing keyword searches. +class EditKeywordControllerBase { + public: + class Delegate { + public: + virtual ~Delegate() {} + + // Invoked from the EditKeywordController when the user accepts the edits. + // NOTE: |template_url| is the value supplied to EditKeywordController's + // constructor, and may be null. A null value indicates a new TemplateURL + // should be created rather than modifying an existing TemplateURL. + virtual void OnEditedKeyword(const TemplateURL* template_url, + const std::wstring& title, + const std::wstring& keyword, + const std::wstring& url) = 0; + }; + + // The |template_url| and/or |edit_keyword_delegate| may be NULL. + EditKeywordControllerBase(const TemplateURL* template_url, + Delegate* edit_keyword_delegate, + Profile* profile); + virtual ~EditKeywordControllerBase() {} + + protected: + // Interface to platform specific view + virtual std::wstring GetURLInput() const = 0; + virtual std::wstring GetKeywordInput() const = 0; + virtual std::wstring GetTitleInput() const = 0; + + // Check if content of Title entry is valid. + bool IsTitleValid() const; + + // Returns true if the currently input URL is valid. The URL is valid if it + // contains no search terms and is a valid url, or if it contains a search + // term and replacing that search term with a character results in a valid + // url. + bool IsURLValid() const; + + // Fixes up and returns the URL the user has input. The returned URL is + // suitable for use by TemplateURL. + std::wstring GetURL() const; + + // Returns whether the currently entered keyword is valid. The keyword is + // valid if it is non-empty and does not conflict with an existing entry. + // NOTE: this is just the keyword, not the title and url. + bool IsKeywordValid() const; + + // Deletes an unused TemplateURL, if its add was cancelled and it's not + // already owned by the TemplateURLModel. + void AcceptAddOrEdit(); + + // Deletes an unused TemplateURL, if its add was cancelled and it's not + // already owned by the TemplateURLModel. + void CleanUpCancelledAdd(); + + const TemplateURL* template_url() const { + return template_url_; + } + + const Profile* profile() const { + return profile_; + } + + private: + // The TemplateURL we're displaying information for. It may be NULL. If we + // have a keyword_editor_view, we assume that this TemplateURL is already in + // the TemplateURLModel; if not, we assume it isn't. + const TemplateURL* template_url_; + + // We may have been created by this, in which case we will call back to it on + // success to add/modify the entry. May be NULL. + Delegate* edit_keyword_delegate_; + + // Profile whose TemplateURLModel we're modifying. + Profile* profile_; +}; + +#endif // CHROME_BROWSER_SEARCH_ENGINES_EDIT_KEYWORD_CONTROLLER_BASE_H_ diff --git a/chrome/browser/views/edit_keyword_controller.cc b/chrome/browser/views/edit_keyword_controller.cc index d8167f1..f37dddf 100644 --- a/chrome/browser/views/edit_keyword_controller.cc +++ b/chrome/browser/views/edit_keyword_controller.cc @@ -7,12 +7,7 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/string_util.h" -#include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/net/url_fixer_upper.h" -#include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url.h" -#include "chrome/browser/search_engines/template_url_model.h" -#include "chrome/browser/views/keyword_editor_view.h" #include "googleurl/src/gurl.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" @@ -40,13 +35,10 @@ std::wstring GetDisplayURL(const TemplateURL& turl) { EditKeywordController::EditKeywordController( HWND parent, const TemplateURL* template_url, - KeywordEditorView* keyword_editor_view, + Delegate* delegate, Profile* profile) - : parent_(parent), - template_url_(template_url), - keyword_editor_view_(keyword_editor_view), - profile_(profile) { - DCHECK(profile_); + : EditKeywordControllerBase(template_url, delegate, profile), + parent_(parent) { Init(); } @@ -73,7 +65,7 @@ bool EditKeywordController::IsModal() const { } std::wstring EditKeywordController::GetWindowTitle() const { - return l10n_util::GetString(template_url_ ? + return l10n_util::GetString(template_url() ? IDS_SEARCH_ENGINES_EDITOR_EDIT_WINDOW_TITLE : IDS_SEARCH_ENGINES_EDITOR_NEW_WINDOW_TITLE); } @@ -81,7 +73,7 @@ std::wstring EditKeywordController::GetWindowTitle() const { bool EditKeywordController::IsDialogButtonEnabled( MessageBoxFlags::DialogButton button) const { if (button == MessageBoxFlags::DIALOGBUTTON_OK) { - return (IsKeywordValid() && !title_tf_->text().empty() && IsURLValid()); + return (IsKeywordValid() && IsTitleValid() && IsURLValid()); } return true; } @@ -97,55 +89,7 @@ bool EditKeywordController::Cancel() { } bool EditKeywordController::Accept() { - std::wstring url_string = GetURL(); - DCHECK(!url_string.empty()); - const std::wstring& keyword = keyword_tf_->text(); - - const TemplateURL* existing = - profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword); - if (existing && - (!keyword_editor_view_ || existing != template_url_)) { - // An entry may have been added with the same keyword string while the - // user edited the dialog, either automatically or by the user (if we're - // confirming a JS addition, they could have the Options dialog open at the - // same time). If so, just ignore this add. - // TODO(pamg): Really, we should modify the entry so this later one - // overwrites it. But we don't expect this case to be common. - CleanUpCancelledAdd(); - return true; - } - - if (!keyword_editor_view_) { - // Confiming an entry we got from JS. We have a template_url_, but it - // hasn't yet been added to the model. - DCHECK(template_url_); - // const_cast is ugly, but this is the same thing the TemplateURLModel - // does in a similar situation (updating an existing TemplateURL with - // data from a new one). - TemplateURL* modifiable_url = const_cast<TemplateURL*>(template_url_); - modifiable_url->set_short_name(title_tf_->text()); - modifiable_url->set_keyword(keyword); - modifiable_url->SetURL(url_string, 0, 0); - // TemplateURLModel takes ownership of template_url_. - profile_->GetTemplateURLModel()->Add(modifiable_url); - UserMetrics::RecordAction(L"KeywordEditor_AddKeywordJS", profile_); - } else if (!template_url_) { - // Adding a new entry via the KeywordEditorView. - DCHECK(keyword_editor_view_); - if (keyword_editor_view_) - keyword_editor_view_->AddTemplateURL(title_tf_->text(), - keyword_tf_->text(), - url_string); - } else { - // Modifying an entry via the KeywordEditorView. - DCHECK(keyword_editor_view_); - if (keyword_editor_view_) { - keyword_editor_view_->ModifyTemplateURL(template_url_, - title_tf_->text(), - keyword_tf_->text(), - url_string); - } - } + AcceptAddOrEdit(); return true; } @@ -168,13 +112,13 @@ bool EditKeywordController::HandleKeystroke( void EditKeywordController::Init() { // Create the views we'll need. view_ = new views::View(); - if (template_url_) { - title_tf_ = CreateTextfield(template_url_->short_name(), false); - keyword_tf_ = CreateTextfield(template_url_->keyword(), true); - url_tf_ = CreateTextfield(GetDisplayURL(*template_url_), false); + if (template_url()) { + title_tf_ = CreateTextfield(template_url()->short_name(), false); + keyword_tf_ = CreateTextfield(template_url()->keyword(), true); + url_tf_ = CreateTextfield(GetDisplayURL(*template_url()), false); // We don't allow users to edit prepopulate URLs. This is done as // occasionally we need to update the URL of prepopulated TemplateURLs. - url_tf_->SetReadOnly(template_url_->prepopulate_id() != 0); + url_tf_->SetReadOnly(template_url()->prepopulate_id() != 0); } else { title_tf_ = CreateTextfield(std::wstring(), false); keyword_tf_ = CreateTextfield(std::wstring(), true); @@ -282,65 +226,23 @@ Textfield* EditKeywordController::CreateTextfield(const std::wstring& text, return text_field; } -bool EditKeywordController::IsURLValid() const { - std::wstring url = GetURL(); - if (url.empty()) - return false; - - // Use TemplateURLRef to extract the search placeholder. - TemplateURLRef template_ref(url, 0, 0); - if (!template_ref.IsValid()) - return false; - - if (!template_ref.SupportsReplacement()) - return GURL(url).is_valid(); - - // If the url has a search term, replace it with a random string and make - // sure the resulting URL is valid. We don't check the validity of the url - // with the search term as that is not necessarily valid. - return GURL(WideToUTF8(template_ref.ReplaceSearchTerms(TemplateURL(), L"a", - TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()))).is_valid(); +std::wstring EditKeywordController::GetURLInput() const { + return url_tf_->text(); } -std::wstring EditKeywordController::GetURL() const { - std::wstring url; - TrimWhitespace(TemplateURLRef::DisplayURLToURLRef(url_tf_->text()), - TRIM_ALL, &url); - if (url.empty()) - return url; - - // Parse the string as a URL to determine the scheme. If we need to, add the - // scheme. As the scheme may be expanded (as happens with {google:baseURL}) - // we need to replace the search terms before testing for the scheme. - TemplateURL t_url; - t_url.SetURL(url, 0, 0); - std::wstring expanded_url = - t_url.url()->ReplaceSearchTerms(t_url, L"x", 0, std::wstring()); - url_parse::Parsed parts; - std::string scheme( - URLFixerUpper::SegmentURL(WideToUTF8(expanded_url), &parts)); - if(!parts.scheme.is_valid()) { - scheme.append("://"); - url.insert(0, UTF8ToWide(scheme)); - } - - return url; +std::wstring EditKeywordController::GetKeywordInput() const { + return keyword_tf_->text(); } -bool EditKeywordController::IsKeywordValid() const { - std::wstring keyword = keyword_tf_->text(); - if (keyword.empty()) - return true; // Always allow no keyword. - const TemplateURL* turl_with_keyword = - profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword); - return (turl_with_keyword == NULL || turl_with_keyword == template_url_); +std::wstring EditKeywordController::GetTitleInput() const { + return title_tf_->text(); } void EditKeywordController::UpdateImageViews() { UpdateImageView(keyword_iv_, IsKeywordValid(), IDS_SEARCH_ENGINES_INVALID_KEYWORD_TT); UpdateImageView(url_iv_, IsURLValid(), IDS_SEARCH_ENGINES_INVALID_URL_TT); - UpdateImageView(title_iv_, !title_tf_->text().empty(), + UpdateImageView(title_iv_, IsTitleValid(), IDS_SEARCH_ENGINES_INVALID_TITLE_TT); } @@ -359,12 +261,3 @@ void EditKeywordController::UpdateImageView(ImageView* image_view, IDR_INPUT_ALERT)); } } - -void EditKeywordController::CleanUpCancelledAdd() { - if (!keyword_editor_view_ && template_url_) { - // When we have no KeywordEditorView, we know that the template_url_ - // hasn't yet been added to the model, so we need to clean it up. - delete template_url_; - template_url_ = NULL; - } -} diff --git a/chrome/browser/views/edit_keyword_controller.h b/chrome/browser/views/edit_keyword_controller.h index 432ed14..fe79f4f 100644 --- a/chrome/browser/views/edit_keyword_controller.h +++ b/chrome/browser/views/edit_keyword_controller.h @@ -12,6 +12,7 @@ #include <windows.h> +#include "chrome/browser/search_engines/edit_keyword_controller_base.h" #include "views/controls/textfield/textfield.h" #include "views/window/dialog_delegate.h" @@ -21,18 +22,18 @@ class ImageView; class Window; } -class KeywordEditorView; class Profile; class TemplateURL; class TemplateURLModel; class EditKeywordController : public views::Textfield::Controller, - public views::DialogDelegate { + public views::DialogDelegate, + public EditKeywordControllerBase { public: - // The template_url and/or keyword_editor_view may be NULL. + // The |template_url| and/or |delegate| may be NULL. EditKeywordController(HWND parent, const TemplateURL* template_url, - KeywordEditorView* keyword_editor_view, + Delegate* delegate, Profile* profile); virtual ~EditKeywordController() {} @@ -69,20 +70,10 @@ class EditKeywordController : public views::Textfield::Controller, // Textfield is configured to map all input to lower case. views::Textfield* CreateTextfield(const std::wstring& text, bool lowercase); - // Returns true if the currently input URL is valid. The URL is valid if it - // contains no search terms and is a valid url, or if it contains a search - // term and replacing that search term with a character results in a valid - // url. - bool IsURLValid() const; - - // Returns the URL the user has input. The returned URL is suitable for use - // by TemplateURL. - std::wstring GetURL() const; - - // Returns whether the currently entered keyword is valid. The keyword is - // valid if it is non-empty and does not conflict with an existing entry. - // NOTE: this is just the keyword, not the title and url. - bool IsKeywordValid() const; + // EditKeywordControllerBase overrides + virtual std::wstring GetURLInput() const; + virtual std::wstring GetKeywordInput() const; + virtual std::wstring GetTitleInput() const; // Invokes UpdateImageView for each of the images views. void UpdateImageViews(); @@ -94,28 +85,12 @@ class EditKeywordController : public views::Textfield::Controller, bool is_valid, int invalid_message_id); - // Deletes an unused TemplateURL, if its add was cancelled and it's not - // already owned by the TemplateURLModel. - void CleanUpCancelledAdd(); - - // The TemplateURL we're displaying information for. It may be NULL. If we - // have a keyword_editor_view, we assume that this TemplateURL is already in - // the TemplateURLModel; if not, we assume it isn't. - const TemplateURL* template_url_; - // Used to parent window to. May be NULL or an invalid window. HWND parent_; // View containing the buttons, text fields ... views::View* view_; - // We may have been created by this, in which case we will call back to it on - // success to add/modify the entry. May be NULL. - KeywordEditorView* keyword_editor_view_; - - // Profile whose TemplateURLModel we're modifying. - Profile* profile_; - // Text fields. views::Textfield* title_tf_; views::Textfield* keyword_tf_; diff --git a/chrome/browser/views/keyword_editor_view.cc b/chrome/browser/views/keyword_editor_view.cc index b5c1e56..bfe3065 100644 --- a/chrome/browser/views/keyword_editor_view.cc +++ b/chrome/browser/views/keyword_editor_view.cc @@ -375,6 +375,17 @@ KeywordEditorView::~KeywordEditorView() { } } +void KeywordEditorView::OnEditedKeyword(const TemplateURL* template_url, + const std::wstring& title, + const std::wstring& keyword, + const std::wstring& url) { + if (template_url) { + ModifyTemplateURL(template_url, title, keyword, url); + } else { + AddTemplateURL(title, keyword, url); + } +} + void KeywordEditorView::AddTemplateURL(const std::wstring& title, const std::wstring& keyword, const std::wstring& url) { diff --git a/chrome/browser/views/keyword_editor_view.h b/chrome/browser/views/keyword_editor_view.h index 1b70641..a0b56ad 100644 --- a/chrome/browser/views/keyword_editor_view.h +++ b/chrome/browser/views/keyword_editor_view.h @@ -9,6 +9,7 @@ #include <map> #include "app/table_model.h" +#include "chrome/browser/search_engines/edit_keyword_controller_base.h" #include "chrome/browser/search_engines/template_url_model.h" #include "views/controls/button/button.h" #include "views/controls/table/table_view_observer.h" @@ -119,7 +120,8 @@ class KeywordEditorView : public views::View, public views::TableViewObserver, public views::ButtonListener, public TemplateURLModelObserver, - public views::DialogDelegate { + public views::DialogDelegate, + public EditKeywordControllerBase::Delegate { friend class KeywordEditorViewTest; FRIEND_TEST(KeywordEditorViewTest, MakeDefault); public: @@ -130,6 +132,13 @@ class KeywordEditorView : public views::View, explicit KeywordEditorView(Profile* profile); virtual ~KeywordEditorView(); + // Overridden from EditKeywordControllerBase::Delegate. + // Calls AddTemplateURL or ModifyTemplateURL as appropriate. + virtual void OnEditedKeyword(const TemplateURL* template_url, + const std::wstring& title, + const std::wstring& keyword, + const std::wstring& url); + // Invoked when the user succesfully fills out the add keyword dialog. // Propagates the change to the TemplateURLModel and updates the table model. void AddTemplateURL(const std::wstring& title, |