Chromium Code Reviews| Index: chrome/browser/ui/views/omnibox/omnibox_result_view.cc |
| diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc |
| index fbddb5da4057d6d07acd754fd30d7f30f0d57be1..8f158d1d66521e21857212fd783e06d0392ea2b0 100644 |
| --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc |
| +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc |
| @@ -17,6 +17,8 @@ |
| #include "base/memory/scoped_vector.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| +#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h" |
| +#include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" |
| #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
| #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" |
| @@ -38,6 +40,33 @@ using ui::NativeTheme; |
| namespace { |
| +// The observer watches for changes in the image being downloaded. |
| +class AnswersImageObserverDesktop : public BitmapFetcherService::Observer { |
| + public: |
| + explicit AnswersImageObserverDesktop( |
| + gfx::ImageSkia* image, views::View* view): |
| + image_(image), |
| + view_(view) |
| + {} |
|
Peter Kasting
2015/02/13 03:01:07
Please read the Google style guide on how to forma
dschuyler
2015/02/13 22:25:25
Done.
|
| + |
| + void OnImageChanged( |
| + BitmapFetcherService::RequestId request_id, |
| + const SkBitmap& answers_image) override { |
| + DCHECK(!answers_image.empty()); |
| + |
| + *image_ = gfx::ImageSkia::CreateFrom1xBitmap(answers_image); |
|
groby-ooo-7-16
2015/02/13 02:30:56
Please don't communicate via shared memory. Pass t
dschuyler
2015/02/13 22:25:25
Done.
|
| + |
| + // Setup a redraw event so the icon will be drawn sooner. |
| + // Without this it will look like the icon is taking longer to download |
| + // than it is truly taking. |
|
Peter Kasting
2015/02/13 03:01:07
It seems like if you didn't do this we could poten
dschuyler
2015/02/13 22:25:26
Empirically, something else eventually causes a pa
|
| + view_->SchedulePaint(); |
| + } |
| + |
| + private: |
| + gfx::ImageSkia* image_; |
| + views::View* view_; |
|
groby-ooo-7-16
2015/02/13 02:30:56
What exactly is the ownership situation? Is view_
Peter Kasting
2015/02/13 03:01:07
In that sense, why not just make the view a Bitmap
groby-ooo-7-16
2015/02/13 06:03:47
Because the ImageFetcher takes ownership of the ob
Peter Kasting
2015/02/13 21:59:32
Can we Just Fix That? That design is atypical of
dschuyler
2015/02/13 22:25:25
Thanks for pointing out this over-site. I intende
dschuyler
2015/02/13 22:25:25
Acknowledged.
dschuyler
2015/02/13 22:25:26
Acknowledged.
groby-ooo-7-16
2015/02/13 22:47:22
Filed http://crbug.com/458681 to fix this. (base::
|
| +}; |
|
Peter Kasting
2015/02/13 03:01:07
DISALLOW_COPY_AND_ASSIGN
dschuyler
2015/02/13 22:25:25
Done.
|
| + |
| // The minimum distance between the top and bottom of the {icon|text} and the |
| // top or bottom of the row. |
| const int kMinimumIconVerticalPadding = 2; |
| @@ -127,7 +156,8 @@ OmniboxResultView::OmniboxResultView(OmniboxPopupContentsView* model, |
| int model_index, |
| LocationBarView* location_bar_view, |
| const gfx::FontList& font_list) |
| - : edge_item_padding_(LocationBarView::kItemPadding), |
| + : request_id_(BitmapFetcherService::REQUEST_ID_INVALID), |
| + edge_item_padding_(LocationBarView::kItemPadding), |
| item_padding_(LocationBarView::kItemPadding), |
| minimum_text_vertical_padding_(kMinimumTextVerticalPadding), |
| model_(model), |
| @@ -227,7 +257,7 @@ void OmniboxResultView::PaintMatch( |
| gfx::RenderText* contents, |
| gfx::RenderText* description, |
| gfx::Canvas* canvas, |
| - int x) const { |
| + int x) { |
| int y = text_bounds_.y(); |
| if (!separator_rendertext_) { |
| @@ -253,6 +283,27 @@ void OmniboxResultView::PaintMatch( |
| if (description_max_width != 0) { |
| x = DrawRenderText(match, separator_rendertext_.get(), false, canvas, x, y, |
| separator_width_); |
| + |
| + if (match.answer && match_.answer->second_line().image_url().is_valid()) { |
| + // Draw the answer/description image. |
| + gfx::ImageSkia image = GetAnswerIcon(); |
| + if (image.width()) |
|
Peter Kasting
2015/02/13 03:01:07
This should probably be !image.size().IsEmpty()
dschuyler
2015/02/13 22:25:26
Done.
|
| + canvas->DrawImageInt( |
| + image, |
| + // Source x, y, w, h. |
| + 0, |
| + 0, |
| + image.width(), |
| + image.height(), |
| + // Destination x, y, w, h. |
| + GetMirroredXInView(x), |
| + y + kMinimumIconVerticalPadding, |
| + default_icon_size_, |
| + default_icon_size_, |
| + true); |
| + x += default_icon_size_ + LocationBarView::kIconInternalPadding; |
|
Peter Kasting
2015/02/13 03:01:07
How come we draw the |image| size, but then we ste
dschuyler
2015/02/13 22:25:25
Maybe I'm confused, but I think that the destinati
Peter Kasting
2015/02/13 22:36:36
I think you're right. I read the code explicitly
|
| + } |
| + |
| DrawRenderText(match, description, false, canvas, x, y, |
| description_max_width); |
| } |
| @@ -425,6 +476,47 @@ int OmniboxResultView::GetDisplayOffset( |
| // static |
| int OmniboxResultView::default_icon_size_ = 0; |
| +gfx::ImageSkia OmniboxResultView::GetAnswerIcon() { |
|
Peter Kasting
2015/02/13 03:01:07
There's no real need to return |answer_image_| in
dschuyler
2015/02/13 22:25:26
Done.
|
| + // Check to see if we have already requested this image. |
| + const GURL& image_url = match_.answer->second_line().image_url(); |
| + if (image_url.is_valid() && image_url == image_url_) |
|
groby-ooo-7-16
2015/02/13 02:30:56
We don't care about this condition. ImageFetcher I
dschuyler
2015/02/13 22:25:25
I removed the "image_url.is_valid() && " part. I
Peter Kasting
2015/02/13 22:36:36
Depends on how frequent this is. I probably would
groby-ooo-7-16
2015/02/13 22:47:22
You shouldn't call GetAnswerIcon unless there's a
|
| + // We have already requested it. |
| + return answer_image_; |
| + |
| + // We don't have that image, so we will try to get it. |
| + answer_image_ = gfx::ImageSkia(); |
| + |
| + // Make a new image download request. |
| + Profile* profile = location_bar_view_->profile(); |
|
groby-ooo-7-16
2015/02/13 02:30:56
Can |profile| _ever_ be NULL here?
Peter Kasting
2015/02/13 03:01:07
I don't think so.
dschuyler
2015/02/13 22:25:25
Acknowledged.
dschuyler
2015/02/13 22:25:26
Done.
|
| + if (!profile) |
| + return answer_image_; |
| + content::BrowserContext* browser_context = profile; |
|
groby-ooo-7-16
2015/02/13 02:30:56
No need for the temporary, just pass the profile d
dschuyler
2015/02/13 22:25:25
Done.
|
| + if (!browser_context) |
| + return answer_image_; |
| + BitmapFetcherService* image_service = |
| + BitmapFetcherServiceFactory::GetForBrowserContext(browser_context); |
| + if (!image_service) |
|
groby-ooo-7-16
2015/02/13 02:30:56
Just DCHECK it's not NULL. It never should be, so
dschuyler
2015/02/13 22:25:25
Done.
|
| + return answer_image_; |
| + |
| + if (request_id_ != BitmapFetcherService::REQUEST_ID_INVALID) { |
|
groby-ooo-7-16
2015/02/13 02:30:56
Just call CancelRequest, without all the testing.
dschuyler
2015/02/13 22:25:25
Done.
|
| + // Cancel the prior request. |
| + image_service->CancelRequest(request_id_); |
| + // Request the new url instead of the prior one. |
| + request_id_ = BitmapFetcherService::REQUEST_ID_INVALID; |
| + } |
| + |
| + // Request the new image. |
| + AnswersImageObserverDesktop* observer = |
| + new AnswersImageObserverDesktop(&answer_image_, this); |
| + if (observer) { |
|
groby-ooo-7-16
2015/02/13 02:30:56
Skip the test - new can't fail. (If it does, crash
Peter Kasting
2015/02/13 03:01:07
To be more precise: We have a memory allocator tha
dschuyler
2015/02/13 22:25:25
Done.
dschuyler
2015/02/13 22:25:25
Acknowledged.
|
| + image_url_ = image_url; |
| + request_id_ = image_service->RequestImage(image_url, observer); |
| + } |
| + |
| + // Return what we have (it may already be valid if the image was cached). |
| + return answer_image_; |
|
groby-ooo-7-16
2015/02/13 02:30:56
No need to return an image if you always request -
Peter Kasting
2015/02/13 03:01:07
If OnImageChanged() is called synchronously in the
groby-ooo-7-16
2015/02/13 06:03:47
It is called synchronously when data is retrieved
dschuyler
2015/02/13 22:25:25
Acknowledged.
dschuyler
2015/02/13 22:25:25
Done.
|
| +} |
| + |
| const char* OmniboxResultView::GetClassName() const { |
| return "OmniboxResultView"; |
| } |