summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_tabs_module.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extension_tabs_module.cc')
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc306
1 files changed, 220 insertions, 86 deletions
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index 41663dd..d219152 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -18,11 +18,30 @@
#include "chrome/common/temp_scaffolding_stubs.h"
#endif
+namespace {
+// keys
+const wchar_t* kIdKey = L"id";
+const wchar_t* kIndexKey = L"index";
+const wchar_t* kWindowIdKey = L"windowId";
+const wchar_t* kUrlKey = L"url";
+const wchar_t* kTitleKey = L"title";
+const wchar_t* kSelectedKey = L"selected";
+const wchar_t* kFocusedKey = L"focused";
+const wchar_t* kFavIconUrlKey = L"favIconUrl";
+const wchar_t* kLeftKey = L"left";
+const wchar_t* kTopKey = L"top";
+const wchar_t* kWidthKey = L"width";
+const wchar_t* kHeightKey = L"height";
+const wchar_t* kTabsKey = L"tabs";
+}
+
// Forward declare static helper functions defined below.
-static DictionaryValue* CreateWindowValue(Browser* browser);
+static DictionaryValue* CreateWindowValue(Browser* browser, bool populate_tabs);
static ListValue* CreateTabList(Browser* browser);
static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id,
int* tab_index);
+static Browser *GetBrowserInProfileWithId(Profile* profile,
+ const int window_id);
// ExtensionTabUtil
int ExtensionTabUtil::GetWindowId(const Browser* browser) {
@@ -56,53 +75,68 @@ DictionaryValue* ExtensionTabUtil::CreateTabValue(
DictionaryValue* ExtensionTabUtil::CreateTabValue(
const TabContents* contents, TabStripModel* tab_strip, int tab_index) {
DictionaryValue* result = new DictionaryValue();
- result->SetInteger(L"id", ExtensionTabUtil::GetTabId(contents));
- result->SetInteger(L"index", tab_index);
- result->SetInteger(L"windowId", ExtensionTabUtil::GetWindowIdOfTab(contents));
- result->SetString(L"url", contents->GetURL().spec());
- result->SetString(L"title", UTF16ToWide(contents->GetTitle()));
- result->SetBoolean(L"selected",
+ result->SetInteger(kIdKey, ExtensionTabUtil::GetTabId(contents));
+ result->SetInteger(kIndexKey, tab_index);
+ result->SetInteger(kWindowIdKey,
+ ExtensionTabUtil::GetWindowIdOfTab(contents));
+ result->SetString(kUrlKey, contents->GetURL().spec());
+ result->SetString(kTitleKey, UTF16ToWide(contents->GetTitle()));
+ result->SetBoolean(kSelectedKey,
tab_strip && tab_index == tab_strip->selected_index());
NavigationEntry* entry = contents->controller().GetActiveEntry();
if (entry) {
if (entry->favicon().is_valid())
- result->SetString(L"favIconUrl", entry->favicon().url().spec());
+ result->SetString(kFavIconUrlKey, entry->favicon().url().spec());
}
return result;
}
-bool GetWindowsFunction::RunImpl() {
- std::set<int> window_ids;
+static bool GetWindowFunctionHelper(Browser *browser, Profile* profile,
+ scoped_ptr<Value>* result) {
+ // TODO(rafaelw): need "not found" error message.
+ if (browser == NULL || browser->profile() != profile)
+ return false;
- // Look for |ids| named parameter as list of id's to fetch.
- if (args_->IsType(Value::TYPE_DICTIONARY)) {
- ListValue *window_id_list;
- const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
- EXTENSION_FUNCTION_VALIDATE(args->GetList(L"ids", &window_id_list));
- for (ListValue::iterator id = window_id_list->begin();
- id != window_id_list->end(); ++id) {
- int window_id;
- EXTENSION_FUNCTION_VALIDATE((*id)->GetAsInteger(&window_id));
- window_ids.insert(window_id);
- }
- }
+ result->reset(CreateWindowValue(browser, false));
+
+ return true;
+}
+
+// Windows ---------------------------------------------------------------------
- // Default to all windows.
- bool all_windows = (window_ids.size() == 0);
+bool GetWindowFunction::RunImpl() {
+ int window_id;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
+
+ Browser *target = GetBrowserInProfileWithId(profile(), window_id);
+ return GetWindowFunctionHelper(target, profile(), &result_);
+}
+
+bool GetCurrentWindowFunction::RunImpl() {
+ return GetWindowFunctionHelper(dispatcher_->browser(), profile(), &result_);
+}
+
+bool GetFocusedWindowFunction::RunImpl() {
+ return GetWindowFunctionHelper(BrowserList::GetLastActive(), profile(),
+ &result_);
+}
+
+bool GetAllWindowsFunction::RunImpl() {
+ bool populate_tabs = false;
+ if (!args_->IsType(Value::TYPE_NULL)) {
+ EXTENSION_FUNCTION_VALIDATE(args_->GetAsBoolean(&populate_tabs));
+ }
result_.reset(new ListValue());
for (BrowserList::const_iterator browser = BrowserList::begin();
- browser != BrowserList::end(); ++browser) {
- // Only examine browsers in the current profile.
- if ((*browser)->profile() == profile()) {
- if (all_windows || (window_ids.find(ExtensionTabUtil::
- GetWindowId(*browser)) != window_ids.end())) {
- static_cast<ListValue*>(result_.get())->Append(
- CreateWindowValue(*browser));
+ browser != BrowserList::end(); ++browser) {
+ // Only examine browsers in the current profile.
+ if ((*browser)->profile() == profile()) {
+ static_cast<ListValue*>(result_.get())->
+ Append(CreateWindowValue(*browser, populate_tabs));
}
- }
}
return true;
@@ -112,10 +146,12 @@ bool CreateWindowFunction::RunImpl() {
scoped_ptr<GURL> url(new GURL());
// Look for optional url.
- if (args_->IsType(Value::TYPE_DICTIONARY)) {
+ if (!args_->IsType(Value::TYPE_NULL)) {
+ EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
std::string url_input;
- if (args->GetString(L"url", &url_input)) {
+ if (args->HasKey(kUrlKey)) {
+ EXTENSION_FUNCTION_VALIDATE(args->GetString(kUrlKey, &url_input));
url.reset(new GURL(url_input));
if (!url->is_valid()) {
// TODO(rafaelw): need error message/callback here
@@ -143,17 +179,25 @@ bool CreateWindowFunction::RunImpl() {
if (args_->IsType(Value::TYPE_DICTIONARY)) {
const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
int bounds_val;
- if (args->GetInteger(L"left", &bounds_val))
+ if (args->HasKey(kLeftKey)) {
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(kLeftKey, &bounds_val));
bounds.set_x(bounds_val);
+ }
- if (args->GetInteger(L"top", &bounds_val))
+ if (args->HasKey(kTopKey)) {
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(kTopKey, &bounds_val));
bounds.set_y(bounds_val);
+ }
- if (args->GetInteger(L"width", &bounds_val))
+ if (args->HasKey(kWidthKey)) {
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(kWidthKey, &bounds_val));
bounds.set_width(bounds_val);
+ }
- if (args->GetInteger(L"height", &bounds_val))
+ if (args->HasKey(kHeightKey)) {
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(kHeightKey, &bounds_val));
bounds.set_height(bounds_val);
+ }
}
Browser *new_window = Browser::Create(dispatcher_->profile());
@@ -169,7 +213,7 @@ bool CreateWindowFunction::RunImpl() {
// TODO(rafaelw): support |focused|, |zIndex|
- result_.reset(CreateWindowValue(new_window));
+ result_.reset(CreateWindowValue(new_window, false));
return true;
}
@@ -200,12 +244,44 @@ bool RemoveWindowFunction::RunImpl() {
return true;
}
+// Tabs ---------------------------------------------------------------------
-bool GetTabsForWindowFunction::RunImpl() {
- EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_NULL));
+bool GetSelectedTabFunction::RunImpl() {
+ int window_id;
+ Browser *browser;
+ // windowId defaults to "current" window.
+ if (!args_->IsType(Value::TYPE_NULL)) {
+ EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
+ browser = GetBrowserInProfileWithId(profile(), window_id);
+ } else {
+ browser = dispatcher_->browser();
+ }
- Browser* browser = dispatcher_->browser();
if (!browser)
+ // TODO(rafaelw): return a "no 'current' browser" error.
+ return false;
+
+ TabStripModel* tab_strip = browser->tabstrip_model();
+ result_.reset(ExtensionTabUtil::CreateTabValue(
+ tab_strip->GetSelectedTabContents(),
+ tab_strip,
+ tab_strip->selected_index()));
+ return true;
+}
+
+bool GetAllTabsInWindowFunction::RunImpl() {
+ int window_id;
+ Browser *browser;
+ // windowId defaults to "current" window.
+ if (!args_->IsType(Value::TYPE_NULL)) {
+ EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&window_id));
+ browser = GetBrowserInProfileWithId(profile(), window_id);
+ } else {
+ browser = dispatcher_->browser();
+ }
+
+ if (!browser)
+ // TODO(rafaelw): return a "no 'current' browser" error.
return false;
result_.reset(CreateTabList(browser));
@@ -217,8 +293,18 @@ bool CreateTabFunction::RunImpl() {
EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
- Browser* browser = BrowserList::GetLastActive();
+ int window_id;
+ Browser *browser;
+ // windowId defaults to "current" window.
+ if (args->HasKey(kWindowIdKey)) {
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(kWindowIdKey, &window_id));
+ browser = GetBrowserInProfileWithId(profile(), window_id);
+ } else {
+ browser = dispatcher_->browser();
+ }
+
if (!browser)
+ // TODO(rafaelw): return a "no 'current' browser" error.
return false;
TabStripModel *tab_strip = browser->tabstrip_model();
@@ -228,18 +314,29 @@ bool CreateTabFunction::RunImpl() {
// -title
// -favIconUrl
- std::string url;
- args->GetString(L"url", &url);
+ std::string url_string;
+ scoped_ptr<GURL> url;
+ if (args->HasKey(kUrlKey)) {
+ EXTENSION_FUNCTION_VALIDATE(args->GetString(kUrlKey, &url_string));
+ url.reset(new GURL(url_string));
+
+ // TODO(rafaelw): return an "invalid url" error.
+ if (!url->is_valid())
+ return false;
+ }
// Default to foreground for the new tab. The presence of 'selected' property
// will override this default.
bool selected = true;
- args->GetBoolean(L"selected", &selected);
+ if (args->HasKey(kSelectedKey))
+ EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(kSelectedKey, &selected));
// If index is specified, honor the value, but keep it bound to
// 0 <= index <= tab_strip->count()
int index = -1;
- args->GetInteger(L"index", &index);
+ if (args->HasKey(kIndexKey))
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(kIndexKey, &index));
+
if (index < 0) {
// Default insert behavior
index = -1;
@@ -248,7 +345,7 @@ bool CreateTabFunction::RunImpl() {
index = tab_strip->count();
}
- TabContents* contents = browser->AddTabWithURL(GURL(url), GURL(),
+ TabContents* contents = browser->AddTabWithURL(*(url.get()), GURL(),
PageTransition::LINK, selected, index, NULL);
index = tab_strip->GetIndexOfTabContents(contents);
@@ -263,27 +360,41 @@ bool GetTabFunction::RunImpl() {
int tab_id;
EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&tab_id));
- Browser* browser = BrowserList::GetLastActive();
- if (!browser)
- return false;
+ int tab_index = -1;
+ Browser *target = NULL;
+ TabStripModel *tab_strip = NULL;
+ for (BrowserList::const_iterator browser = BrowserList::begin();
+ browser != BrowserList::end(); ++browser) {
+ if ((*browser)->profile() == profile()) {
+ target = *browser;
+ tab_strip = (*browser)->tabstrip_model();
+ if (GetIndexOfTabId(tab_strip, tab_id, &tab_index)) {
+ break;
+ }
+ }
+ }
- int tab_index;
- TabStripModel* tab_strip = browser->tabstrip_model();
- // TODO(rafaelw): return an error if the tab is not found by |tab_id|
- if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
+ if (target == NULL || tab_index == -1) {
+ // TODO(rafaelw): need "not found" error message.
return false;
+ }
- result_.reset(ExtensionTabUtil::CreateTabValue(
- tab_strip->GetTabContentsAt(tab_index), tab_strip, tab_index));
+ TabContents *contents = target->tabstrip_model()->GetTabContentsAt(tab_index);
+ result_.reset(ExtensionTabUtil::CreateTabValue(contents, tab_strip,
+ tab_index));
return true;
}
bool UpdateTabFunction::RunImpl() {
int tab_id;
- EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
- const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
- EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"id", &tab_id));
-
+ EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
+ const ListValue *args = static_cast<const ListValue*>(args_);
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(0, &tab_id));
+ DictionaryValue *update_props;
+ EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &update_props));
+
+ // TODO(rafaelw): Need to search for appropriate browser that contains
+ // |tab_id|.
Browser* browser = BrowserList::GetLastActive();
if (!browser)
return false;
@@ -303,22 +414,26 @@ bool UpdateTabFunction::RunImpl() {
// Navigate the tab to a new location if the url different.
std::string url;
- if (args->GetString(L"url", &url)) {
+ if (update_props->HasKey(kUrlKey)) {
+ EXTENSION_FUNCTION_VALIDATE(update_props->GetString(kUrlKey, &url));
GURL new_gurl(url);
- if (new_gurl.is_valid()) {
- controller.LoadURL(new_gurl, GURL(), PageTransition::LINK);
- } else {
- // TODO(rafaelw): return some reasonable error?
- }
+
+ // TODO(rafaelw): return "invalid url" here.
+ if (!new_gurl.is_valid())
+ return false;
+
+ controller.LoadURL(new_gurl, GURL(), PageTransition::LINK);
}
- bool selected;
+ bool selected = false;
// TODO(rafaelw): Setting |selected| from js doesn't make much sense.
// Move tab selection management up to window.
- if (args->GetBoolean(L"selected", &selected) &&
- selected &&
- tab_strip->selected_index() != tab_index) {
- tab_strip->SelectTabContentsAt(tab_index, false);
+ if (update_props->HasKey(kSelectedKey)) {
+ EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean(kSelectedKey,
+ &selected));
+ if (selected && tab_strip->selected_index() != tab_index) {
+ tab_strip->SelectTabContentsAt(tab_index, false);
+ }
}
return true;
@@ -326,20 +441,23 @@ bool UpdateTabFunction::RunImpl() {
bool MoveTabFunction::RunImpl() {
int tab_id;
+ EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
+ const ListValue *args = static_cast<const ListValue*>(args_);
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(0, &tab_id));
+ DictionaryValue *update_props;
+ EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &update_props));
+
int new_index;
- EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_DICTIONARY));
- const DictionaryValue *args = static_cast<const DictionaryValue*>(args_);
- EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"id", &tab_id));
- EXTENSION_FUNCTION_VALIDATE(args->GetInteger(L"index", &new_index));
+ EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger(kIndexKey, &new_index));
EXTENSION_FUNCTION_VALIDATE(new_index >= 0);
+ // TODO(rafaelw): need to support finding the tab by id in any browser,
+ // not just the currently active browser.
Browser* browser = BrowserList::GetLastActive();
if (!browser)
return false;
-
int tab_index;
TabStripModel* tab_strip = browser->tabstrip_model();
- // TODO(rafaelw): return an error if the tab is not found by |tab_id|
if (!GetIndexOfTabId(tab_strip, tab_id, &tab_index))
return false;
@@ -380,19 +498,24 @@ bool RemoveTabFunction::RunImpl() {
}
// static helpers
-static DictionaryValue* CreateWindowValue(Browser* browser) {
+// if |populate| is true, each window gets a list property |tabs| which contains
+// fully populated tab objects.
+static DictionaryValue* CreateWindowValue(Browser* browser,
+ bool populate_tabs) {
DictionaryValue* result = new DictionaryValue();
- result->SetInteger(L"id", ExtensionTabUtil::GetWindowId(browser));
- result->SetBoolean(L"focused", browser->window()->IsActive());
+ result->SetInteger(kIdKey, ExtensionTabUtil::GetWindowId(browser));
+ result->SetBoolean(kFocusedKey, browser->window()->IsActive());
gfx::Rect bounds = browser->window()->GetNormalBounds();
// TODO(rafaelw): zIndex ?
- result->SetInteger(L"left", bounds.x());
- result->SetInteger(L"top", bounds.y());
- result->SetInteger(L"width", bounds.width());
- result->SetInteger(L"height", bounds.height());
+ result->SetInteger(kLeftKey, bounds.x());
+ result->SetInteger(kTopKey, bounds.y());
+ result->SetInteger(kWidthKey, bounds.width());
+ result->SetInteger(kHeightKey, bounds.height());
- result->Set(L"tabs", CreateTabList(browser));
+ if (populate_tabs) {
+ result->Set(kTabsKey, CreateTabList(browser));
+ }
return result;
}
@@ -419,3 +542,14 @@ static bool GetIndexOfTabId(const TabStripModel* tab_strip, int tab_id,
}
return false;
}
+
+static Browser *GetBrowserInProfileWithId(Profile* profile,
+ const int window_id) {
+ for (BrowserList::const_iterator browser = BrowserList::begin();
+ browser != BrowserList::end(); ++browser) {
+ if ((*browser)->profile() == profile &&
+ ExtensionTabUtil::GetWindowId(*browser) == window_id)
+ return *browser;
+ }
+ return NULL;
+}