summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/location_bar_view_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/cocoa/location_bar_view_mac.mm')
-rw-r--r--chrome/browser/cocoa/location_bar_view_mac.mm282
1 files changed, 274 insertions, 8 deletions
diff --git a/chrome/browser/cocoa/location_bar_view_mac.mm b/chrome/browser/cocoa/location_bar_view_mac.mm
index 5390d20..7e13ff3 100644
--- a/chrome/browser/cocoa/location_bar_view_mac.mm
+++ b/chrome/browser/cocoa/location_bar_view_mac.mm
@@ -6,6 +6,7 @@
#include "app/l10n_util_mac.h"
#include "app/resource_bundle.h"
+#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "chrome/app/chrome_dll_resource.h"
@@ -17,11 +18,17 @@
#import "chrome/browser/cocoa/autocomplete_text_field_cell.h"
#include "chrome/browser/cocoa/event_utils.h"
#include "chrome/browser/command_updater.h"
+#include "chrome/browser/extensions/extension_browser_event_router.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/extensions/extension_tabs_module.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/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_action.h"
+#include "chrome/common/notification_service.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "skia/ext/skia_utils_mac.h"
@@ -85,11 +92,13 @@ LocationBarViewMac::LocationBarViewMac(
field_(field),
disposition_(CURRENT_TAB),
security_image_view_(profile, toolbar_model),
+ page_action_views_(new PageActionViewList(this, profile, toolbar_model)),
profile_(profile),
toolbar_model_(toolbar_model),
transition_(PageTransition::TYPED) {
AutocompleteTextFieldCell* cell = [field_ autocompleteTextFieldCell];
[cell setSecurityImageView:&security_image_view_];
+ [cell setPageActionViewList:page_action_views_];
}
LocationBarViewMac::~LocationBarViewMac() {
@@ -133,6 +142,15 @@ void LocationBarViewMac::FocusSearch() {
// TODO(pkasting): Focus the edit a la Linux/Win
}
+void LocationBarViewMac::UpdatePageActions() {
+ page_action_views_->RefreshViews();
+ [field_ resetFieldEditorFrameIfNeeded];
+}
+
+void LocationBarViewMac::InvalidatePageActions() {
+ page_action_views_->DeleteAll();
+}
+
void LocationBarViewMac::SaveStateToContents(TabContents* contents) {
// TODO(shess): Why SaveStateToContents vs SaveStateToTab?
edit_view_->SaveStateToTab(contents);
@@ -141,6 +159,7 @@ void LocationBarViewMac::SaveStateToContents(TabContents* contents) {
void LocationBarViewMac::Update(const TabContents* contents,
bool should_restore_state) {
SetSecurityIcon(toolbar_model_->GetIcon());
+ page_action_views_->RefreshViews();
// AutocompleteEditView restores state if the tab is non-NULL.
edit_view_->Update(should_restore_state ? contents : NULL);
}
@@ -291,23 +310,34 @@ void LocationBarViewMac::Revert() {
edit_view_->RevertAll();
}
+// TODO(pamg): Change all these, here and for other platforms, to size_t.
int LocationBarViewMac::PageActionCount() {
- NOTIMPLEMENTED();
- return -1;
+ return static_cast<int>(page_action_views_->Count());
}
int LocationBarViewMac::PageActionVisibleCount() {
- NOTIMPLEMENTED();
- return -1;
+ return static_cast<int>(page_action_views_->VisibleCount());
}
ExtensionAction* LocationBarViewMac::GetPageAction(size_t index) {
- NOTIMPLEMENTED();
+ if (index < page_action_views_->Count())
+ return page_action_views_->ViewAt(index)->page_action();
+ NOTREACHED();
return NULL;
}
ExtensionAction* LocationBarViewMac::GetVisiblePageAction(size_t index) {
- NOTIMPLEMENTED();
+ size_t current = 0;
+ for (size_t i = 0; i < page_action_views_->Count(); ++i) {
+ if (page_action_views_->ViewAt(i)->IsVisible()) {
+ if (current == index)
+ return page_action_views_->ViewAt(i)->page_action();
+
+ ++current;
+ }
+ }
+
+ NOTREACHED();
return NULL;
}
@@ -372,6 +402,10 @@ void LocationBarViewMac::LocationBarImageView::SetImage(NSImage* image) {
image_.reset([image retain]);
}
+void LocationBarViewMac::LocationBarImageView::SetImage(SkBitmap* image) {
+ SetImage(gfx::SkBitmapToNSImage(*image));
+}
+
void LocationBarViewMac::LocationBarImageView::SetLabel(NSString* text,
NSFont* baseFont,
NSColor* color) {
@@ -394,7 +428,6 @@ void LocationBarViewMac::LocationBarImageView::SetLabel(NSString* text,
}
void LocationBarViewMac::LocationBarImageView::SetVisible(bool visible) {
- DCHECK(!visible || image_);
visible_ = visible;
}
@@ -432,7 +465,6 @@ void LocationBarViewMac::SecurityImageView::SetImageShown(Image image) {
}
}
-
bool LocationBarViewMac::SecurityImageView::OnMousePressed() {
TabContents* tab = BrowserList::GetLastActive()->GetSelectedTabContents();
NavigationEntry* nav_entry = tab->controller().GetActiveEntry();
@@ -443,3 +475,237 @@ bool LocationBarViewMac::SecurityImageView::OnMousePressed() {
tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true);
return true;
}
+
+// PageActionImageView----------------------------------------------------------
+
+LocationBarViewMac::PageActionImageView::PageActionImageView(
+ LocationBarViewMac* owner,
+ Profile* profile,
+ ExtensionAction* page_action)
+ : owner_(owner),
+ profile_(profile),
+ page_action_(page_action),
+ current_tab_id_(-1),
+ preview_enabled_(false) {
+ Extension* extension = profile->GetExtensionsService()->GetExtensionById(
+ page_action->extension_id(), false);
+ DCHECK(extension);
+
+ // Load all the icons declared in the manifest. This is the contents of the
+ // icons array, plus the default_icon property, if any.
+ std::vector<std::string> icon_paths(*page_action->icon_paths());
+ if (!page_action_->default_icon_path().empty())
+ icon_paths.push_back(page_action_->default_icon_path());
+
+ tracker_ = new ImageLoadingTracker(this, icon_paths.size());
+ for (std::vector<std::string>::iterator iter = icon_paths.begin();
+ iter != icon_paths.end(); ++iter) {
+ tracker_->PostLoadImageTask(extension->GetResource(*iter),
+ gfx::Size(Extension::kPageActionIconMaxSize,
+ Extension::kPageActionIconMaxSize));
+ }
+
+ registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
+ Source<Profile>(profile_));
+}
+
+LocationBarViewMac::PageActionImageView::~PageActionImageView() {
+ if (tracker_)
+ tracker_->StopTrackingImageLoad();
+}
+
+// Overridden from LocationBarImageView. Either notify listeners or show a
+// popup depending on the Page Action.
+bool LocationBarViewMac::PageActionImageView::OnMousePressed(NSRect bounds) {
+ if (page_action_->has_popup()) {
+ NOTIMPLEMENTED();
+ } else {
+ ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
+ profile_, page_action_->extension_id(), page_action_->id(),
+ current_tab_id_, current_url_.spec(),
+ 1); // TODO(pamg): Add support for middle and right buttons.
+ }
+ return true;
+}
+
+void LocationBarViewMac::PageActionImageView::OnImageLoaded(SkBitmap* image,
+ size_t index) {
+ // We loaded icons()->size() icons, plus one extra if the Page Action had
+ // a default icon.
+ int total_icons = page_action_->icon_paths()->size();
+ if (!page_action_->default_icon_path().empty())
+ total_icons++;
+ DCHECK(static_cast<int>(index) < total_icons);
+
+ // Map the index of the loaded image back to its name. If we ever get an
+ // index greater than the number of icons, it must be the default icon.
+ if (image) {
+ if (index < page_action_->icon_paths()->size())
+ page_action_icons_[page_action_->icon_paths()->at(index)] = *image;
+ else
+ page_action_icons_[page_action_->default_icon_path()] = *image;
+ }
+
+ // If we are done, release the tracker.
+ if (static_cast<int>(index) == (total_icons - 1))
+ tracker_ = NULL;
+
+ owner_->UpdatePageActions();
+}
+
+void LocationBarViewMac::PageActionImageView::UpdateVisibility(
+ TabContents* contents, const GURL& url) {
+ // Save this off so we can pass it back to the extension when the action gets
+ // executed. See PageActionImageView::OnMousePressed.
+ current_tab_id_ = ExtensionTabUtil::GetTabId(contents);
+ current_url_ = url;
+
+ bool visible = preview_enabled_ ||
+ page_action_->GetIsVisible(current_tab_id_);
+ if (visible) {
+ // Set the tooltip.
+ tooltip_ = page_action_->GetTitle(current_tab_id_);
+ // TODO(port): implement tooltips
+ //SetTooltipText(ASCIIToWide(tooltip_));
+
+ // Set the image.
+ // It can come from three places. In descending order of priority:
+ // - The developer can set it dynamically by path or bitmap. It will be in
+ // page_action_->GetIcon().
+ // - The developer can set it dynamically by index. It will be in
+ // page_action_->GetIconIndex().
+ // - It can be set in the manifest by path. It will be in page_action_->
+ // default_icon_path().
+
+ // First look for a dynamically set bitmap.
+ SkBitmap skia_icon = page_action_->GetIcon(current_tab_id_);
+ if (skia_icon.isNull()) {
+ int icon_index = page_action_->GetIconIndex(current_tab_id_);
+ std::string icon_path;
+ if (icon_index >= 0)
+ icon_path = page_action_->icon_paths()->at(icon_index);
+ else
+ icon_path = page_action_->default_icon_path();
+
+ if (!icon_path.empty()) {
+ PageActionMap::iterator iter = page_action_icons_.find(icon_path);
+ if (iter != page_action_icons_.end())
+ skia_icon = iter->second;
+ }
+ }
+
+ if (!skia_icon.isNull())
+ SetImage(gfx::SkBitmapToNSImage(skia_icon));
+ }
+ SetVisible(visible);
+}
+
+void LocationBarViewMac::PageActionImageView::Observe(
+ NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE:
+ // If we aren't the host of the popup, then disregard the notification.
+ //if (!popup_ || Details<ExtensionHost>(popup_->host()) != details)
+ // return;
+
+ //HidePopup();
+ NOTIMPLEMENTED();
+ break;
+ default:
+ NOTREACHED() << "Unexpected notification";
+ break;
+ }
+}
+
+// PageActionViewList-----------------------------------------------------------
+
+void LocationBarViewMac::PageActionViewList::DeleteAll() {
+ if (!views_.empty()) {
+ STLDeleteContainerPointers(views_.begin(), views_.end());
+ views_.clear();
+ }
+}
+
+void LocationBarViewMac::PageActionViewList::RefreshViews() {
+ std::vector<ExtensionAction*> page_actions;
+ ExtensionsService* service = profile_->GetExtensionsService();
+ if (!service)
+ return;
+
+ // Remember the previous visibility of the Page Actions so that we can
+ // notify when this changes.
+ std::map<ExtensionAction*, bool> old_visibility;
+ for (size_t i = 0; i < views_.size(); ++i) {
+ old_visibility[views_[i]->page_action()] = views_[i]->IsVisible();
+ }
+
+ for (size_t i = 0; i < service->extensions()->size(); ++i) {
+ if (service->extensions()->at(i)->page_action())
+ page_actions.push_back(service->extensions()->at(i)->page_action());
+ }
+
+ // On startup we sometimes haven't loaded any extensions. This makes sure
+ // we catch up when the extensions (and any Page Actions) load.
+ if (page_actions.size() != views_.size()) {
+ DeleteAll(); // Delete the old views (if any).
+
+ views_.resize(page_actions.size());
+
+ for (size_t i = 0; i < page_actions.size(); ++i) {
+ views_[i] = new PageActionImageView(owner_, profile_, page_actions[i]);
+ views_[i]->SetVisible(false);
+ }
+ }
+
+ if (views_.empty())
+ return;
+
+ Browser* browser = BrowserList::GetLastActive();
+ // The last-active browser can be NULL during startup.
+ if (!browser)
+ return;
+
+ TabContents* contents = browser->GetSelectedTabContents();
+ if (!contents)
+ return;
+
+ GURL url = GURL(WideToUTF8(toolbar_model_->GetText()));
+ for (size_t i = 0; i < views_.size(); ++i) {
+ views_[i]->UpdateVisibility(contents, url);
+ // Check if the visibility of the action changed and notify if it did.
+ ExtensionAction* action = views_[i]->page_action();
+ if (old_visibility.find(action) == old_visibility.end() ||
+ old_visibility[action] != views_[i]->IsVisible()) {
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
+ Source<ExtensionAction>(action),
+ Details<TabContents>(contents));
+ }
+ }
+}
+
+LocationBarViewMac::PageActionImageView*
+ LocationBarViewMac::PageActionViewList::ViewAt(size_t index) {
+ CHECK(index < Count());
+ return views_[index];
+}
+
+size_t LocationBarViewMac::PageActionViewList::Count() {
+ return views_.size();
+}
+
+size_t LocationBarViewMac::PageActionViewList::VisibleCount() {
+ size_t result = 0;
+ for (size_t i = 0; i < views_.size(); ++i) {
+ if (views_[i]->IsVisible())
+ ++result;
+ }
+ return result;
+}
+
+void LocationBarViewMac::PageActionViewList::OnMousePressed(NSRect iconFrame,
+ size_t index) {
+ ViewAt(index)->OnMousePressed(iconFrame);
+}