extension_tabs_module.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_tabs_module.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/base64.h" 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_list.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_window.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_function_dispatcher.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_host.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_infobar_delegate.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_tabs_module_constants.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extensions_service.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/backing_store.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host_delegate.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/navigation_entry.h" 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/tab_contents/tab_contents_view.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tabs/tab_strip_model.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/window_sizer.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_error_utils.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "gfx/codec/jpeg_codec.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "gfx/codec/png_codec.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/image_operations.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/platform_canvas.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace keys = extension_tabs_module_constants; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int CaptureVisibleTabFunction::kDefaultQuality = 90; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Forward declare static helper functions defined below. 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |error_message| can optionally be passed in a will be set with an appropriate 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// message if the window cannot be found by id. 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic Browser* GetBrowserInProfileWithId(Profile* profile, 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int window_id, 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* error_message); 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |error_message| can optionally be passed in and will be set with an 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// appropriate message if the tab cannot be found by id. 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool GetTabById(int tab_id, Profile* profile, 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser** browser, 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel** tab_strip, 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents** contents, 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* tab_index, std::string* error_message); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Takes |url_string| and returns a GURL which is either valid and absolute 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// or invalid. If |url_string| is not directly interpretable as a valid (it is 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// likely a relative URL) an attempt is made to resolve it. |extension| is 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// provided so it can be resolved relative to its extension base 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (chrome-extension://<id>/). Using the source frame url would be more correct, 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// but because the api shipped with urls resolved relative to their extension 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// base, we decided it wasn't worth breaking existing extensions to fix. 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic GURL ResolvePossiblyRelativeURL(std::string url_string, 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Extension* extension); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Return the type name for a browser window type. 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string GetWindowTypeText(Browser::Type type); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint ExtensionTabUtil::GetWindowId(const Browser* browser) { 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return browser->session_id().id(); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint ExtensionTabUtil::GetTabId(const TabContents* tab_contents) { 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab_contents->controller().session_id().id(); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string ExtensionTabUtil::GetTabStatusText(bool is_loading) { 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return is_loading ? keys::kStatusValueLoading : keys::kStatusValueComplete; 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint ExtensionTabUtil::GetWindowIdOfTab(const TabContents* tab_contents) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab_contents->controller().window_id().id(); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDictionaryValue* ExtensionTabUtil::CreateTabValue( 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TabContents* contents) { 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find the tab strip and index of this guy. 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator it = BrowserList::begin(); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != BrowserList::end(); ++it) { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = (*it)->tabstrip_model(); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_index = tab_strip->GetIndexOfTabContents(contents); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_index != -1) { 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ExtensionTabUtil::CreateTabValue(contents, tab_strip, tab_index); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Couldn't find it. This can happen if the tab is being dragged. 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ExtensionTabUtil::CreateTabValue(contents, NULL, -1); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochListValue* ExtensionTabUtil::CreateTabList(const Browser* browser) { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* tab_list = new ListValue(); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = browser->tabstrip_model(); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_strip->count(); ++i) { 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_list->Append(ExtensionTabUtil::CreateTabValue( 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_strip->GetTabContentsAt(i), tab_strip, i)); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab_list; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDictionaryValue* ExtensionTabUtil::CreateTabValue( 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const TabContents* contents, TabStripModel* tab_strip, int tab_index) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* result = new DictionaryValue(); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kIdKey, ExtensionTabUtil::GetTabId(contents)); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kIndexKey, tab_index); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kWindowIdKey, 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionTabUtil::GetWindowIdOfTab(contents)); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetString(keys::kUrlKey, contents->GetURL().spec()); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetString(keys::kStatusKey, GetTabStatusText(contents->is_loading())); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetBoolean(keys::kSelectedKey, 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_strip && tab_index == tab_strip->selected_index()); 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick result->SetString(keys::kTitleKey, contents->GetTitle()); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetBoolean(keys::kIncognitoKey, 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents->profile()->IsOffTheRecord()); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents->is_loading()) { 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationEntry* entry = contents->controller().GetActiveEntry(); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry) { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry->favicon().is_valid()) 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetString(keys::kFavIconUrlKey, entry->favicon().url().spec()); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// if |populate| is true, each window gets a list property |tabs| which contains 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// fully populated tab objects. 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDictionaryValue* ExtensionTabUtil::CreateWindowValue(const Browser* browser, 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool populate_tabs) { 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser->window()); 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* result = new DictionaryValue(); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kIdKey, ExtensionTabUtil::GetWindowId(browser)); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetBoolean(keys::kIncognitoKey, 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->profile()->IsOffTheRecord()); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetBoolean(keys::kFocusedKey, browser->window()->IsActive()); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounds = browser->window()->GetRestoredBounds(); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kLeftKey, bounds.x()); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kTopKey, bounds.y()); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kWidthKey, bounds.width()); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetInteger(keys::kHeightKey, bounds.height()); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->SetString(keys::kWindowTypeKey, GetWindowTypeText(browser->type())); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (populate_tabs) { 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->Set(keys::kTabsKey, ExtensionTabUtil::CreateTabList(browser)); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionTabUtil::GetDefaultTab(Browser* browser, TabContents** contents, 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* tab_id) { 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(contents); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(tab_id); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *contents = browser->tabstrip_model()->GetSelectedTabContents(); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*contents) { 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_id) 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *tab_id = ExtensionTabUtil::GetTabId(*contents); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExtensionTabUtil::GetTabById(int tab_id, Profile* profile, 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser** browser, 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel** tab_strip, 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents** contents, 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* tab_index) { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* target_browser; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* target_tab_strip; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* target_contents; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* incognito_profile = 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick include_incognito && profile->HasOffTheRecordProfile() ? 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile->GetOffTheRecordProfile() : NULL; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator iter = BrowserList::begin(); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter != BrowserList::end(); ++iter) { 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_browser = *iter; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_browser->profile() == profile || 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_browser->profile() == incognito_profile) { 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_tab_strip = target_browser->tabstrip_model(); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < target_tab_strip->count(); ++i) { 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_contents = target_tab_strip->GetTabContentsAt(i); 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_contents->controller().session_id().id() == tab_id) { 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser) 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *browser = target_browser; 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_strip) 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *tab_strip = target_tab_strip; 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents) 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *contents = target_contents; 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_index) 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *tab_index = i; 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Windows --------------------------------------------------------------------- 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetWindowFunction::RunImpl() { 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id; 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = GetBrowserInProfileWithId(profile(), window_id, 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->window()) { 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kWindowNotFoundError, base::IntToString(window_id)); 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateWindowValue(browser, false)); 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetCurrentWindowFunction::RunImpl() { 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = GetCurrentBrowser(); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->window()) { 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateWindowValue(browser, false)); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetLastFocusedWindowFunction::RunImpl() { 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = BrowserList::FindBrowserWithType( 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile(), Browser::TYPE_ANY, include_incognito()); 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->window()) { 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoLastFocusedWindowError; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateWindowValue(browser, false)); 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetAllWindowsFunction::RunImpl() { 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool populate_tabs = false; 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* args; 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kPopulateKey)) { 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kPopulateKey, 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &populate_tabs)); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(new ListValue()); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* incognito_profile = 2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick include_incognito() && profile()->HasOffTheRecordProfile() ? 2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile()->GetOffTheRecordProfile() : NULL; 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator browser = BrowserList::begin(); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser != BrowserList::end(); ++browser) { 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only examine browsers in the current profile that have windows. 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (((*browser)->profile() == profile() || 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*browser)->profile() == incognito_profile) && 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*browser)->window()) { 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<ListValue*>(result_.get())-> 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Append(ExtensionTabUtil::CreateWindowValue(*browser, populate_tabs)); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CreateWindowFunction::RunImpl() { 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* args = NULL; 292731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::vector<GURL> urls; 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Look for optional url. 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args) { 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kUrlKey)) { 300731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Value* url_value; 301731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::vector<std::string> url_strings; 302731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick args->Get(keys::kUrlKey, &url_value); 303731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 304731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // First, get all the URLs the client wants to open. 305731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (url_value->IsType(Value::TYPE_STRING)) { 306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string url_string; 307731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick url_value->GetAsString(&url_string); 308731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick url_strings.push_back(url_string); 309731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else if (url_value->IsType(Value::TYPE_LIST)) { 310731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ListValue* url_list = static_cast<const ListValue*>(url_value); 311731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (size_t i = 0; i < url_list->GetSize(); ++i) { 312731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string url_string; 313731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EXTENSION_FUNCTION_VALIDATE(url_list->GetString(i, &url_string)); 314731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick url_strings.push_back(url_string); 315731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 316731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 317731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 318731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Second, resolve, validate and convert them to GURLs. 319731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (std::vector<std::string>::iterator i = url_strings.begin(); 320731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick i != url_strings.end(); ++i) { 321731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GURL url = ResolvePossiblyRelativeURL(*i, GetExtension()); 322731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!url.is_valid()) { 323731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick error_ = ExtensionErrorUtils::FormatErrorMessage( 324731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick keys::kInvalidUrlError, *i); 325731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 326731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 327731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick urls.push_back(url); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try to position the new browser relative its originating browser window. 333731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gfx::Rect window_bounds; 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool maximized; 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The call offsets the bounds by kWindowTilePixels (defined in WindowSizer to 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be 10) 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE(rafaelw): It's ok if GetCurrentBrowser() returns NULL here. 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GetBrowserWindowBounds will default to saved "default" values for the app. 340731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick WindowSizer::GetBrowserWindowBounds(std::string(), gfx::Rect(), 341731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GetCurrentBrowser(), &window_bounds, 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &maximized); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 344731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Calculate popup bounds separately. In ChromiumOS the default is 0x0 which 345731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // indicates default window sizes in PanelBrowserView. In other OSs popups 346731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // use the same default bounds as windows. 347731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gfx::Rect popup_bounds; 348731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if !defined(OS_CHROMEOS) 349731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds = window_bounds; // Use window size as default for popups 350731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif 351731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* window_profile = profile(); 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser::Type window_type = Browser::TYPE_NORMAL; 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args) { 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Any part of the bounds can optionally be set by the caller. 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bounds_val; 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kLeftKey)) { 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kLeftKey, 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 361731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_bounds.set_x(bounds_val); 362731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds.set_x(bounds_val); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kTopKey)) { 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kTopKey, 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 368731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_bounds.set_y(bounds_val); 369731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds.set_y(bounds_val); 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kWidthKey)) { 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kWidthKey, 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 375731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_bounds.set_width(bounds_val); 376731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds.set_width(bounds_val); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kHeightKey)) { 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kHeightKey, 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 382731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_bounds.set_height(bounds_val); 383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick popup_bounds.set_height(bounds_val); 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool incognito = false; 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kIncognitoKey)) { 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kIncognitoKey, 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &incognito)); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (incognito) 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_profile = window_profile->GetOffTheRecordProfile(); 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string type_str; 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kWindowTypeKey)) { 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kWindowTypeKey, 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &type_str)); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type_str == keys::kWindowTypeValueNormal) { 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_type = Browser::TYPE_NORMAL; 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type_str == keys::kWindowTypeValuePopup) { 401731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick window_type = Browser::TYPE_APP_POPUP; 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(false); 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 408731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Browser* new_window = Browser::CreateForType(window_type, window_profile); 409731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (std::vector<GURL>::iterator i = urls.begin(); i != urls.end(); ++i) { 410731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Browser::AddTabWithURLParams addTabParams = 411731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Browser::AddTabWithURLParams(*i, PageTransition::LINK); 412731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->AddTabWithURL(&addTabParams); 413731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 414731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (urls.size() == 0) 415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->NewTab(); 416731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->SelectNumberedTab(0); 417731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (window_type & Browser::TYPE_POPUP) 418731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->window()->SetBounds(popup_bounds); 419731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick else 420731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_window->window()->SetBounds(window_bounds); 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_window->window()->Show(); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_window->profile()->IsOffTheRecord() && !include_incognito()) { 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't expose incognito windows if the extension isn't allowed. 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(Value::CreateNullValue()); 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 427731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick result_.reset(ExtensionTabUtil::CreateWindowValue(new_window, true)); 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UpdateWindowFunction::RunImpl() { 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id; 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* update_props; 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = GetBrowserInProfileWithId(profile(), window_id, 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->window()) { 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 4433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kWindowNotFoundError, base::IntToString(window_id)); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounds = browser->window()->GetRestoredBounds(); 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Any part of the bounds can optionally be set by the caller. 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bounds_val; 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kLeftKey)) { 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kLeftKey, 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_x(bounds_val); 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kTopKey)) { 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kTopKey, 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_y(bounds_val); 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kWidthKey)) { 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kWidthKey, 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_width(bounds_val); 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kHeightKey)) { 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kHeightKey, 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &bounds_val)); 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_height(bounds_val); 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->window()->SetBounds(bounds); 478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 479731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool selected_val = false; 480731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (update_props->HasKey(keys::kFocusedKey)) { 481731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( 482731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick keys::kFocusedKey, &selected_val)); 483731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (selected_val) 484731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick browser->window()->Activate(); 485731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick else 486731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick browser->window()->Deactivate(); 487731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 488731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateWindowValue(browser, false)); 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveWindowFunction::RunImpl() { 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id; 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = GetBrowserInProfileWithId(profile(), window_id, 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->CloseWindow(); 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tabs ------------------------------------------------------------------------ 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetSelectedTabFunction::RunImpl() { 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser; 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windowId defaults to "current" window. 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = -1; 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetBrowserInProfileWithId(profile(), window_id, 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = browser->tabstrip_model(); 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = tab_strip->GetSelectedTabContents(); 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) { 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoSelectedTabError; 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents, tab_strip, 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_strip->selected_index())); 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetAllTabsInWindowFunction::RunImpl() { 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser; 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windowId defaults to "current" window. 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = -1; 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetBrowserInProfileWithId(profile(), window_id, 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabList(browser)); 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CreateTabFunction::RunImpl() { 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* args; 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser *browser; 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windowId defaults to "current" window. 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = -1; 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kWindowIdKey)) { 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetInteger( 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kWindowIdKey, &window_id)); 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetBrowserInProfileWithId(profile(), window_id, 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(rafaelw): handle setting remaining tab properties: 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // -title 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // -favIconUrl 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string url_string; 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url; 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kUrlKey)) { 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kUrlKey, 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &url_string)); 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url = ResolvePossiblyRelativeURL(url_string, GetExtension()); 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.is_valid()) { 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_string); 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Default to foreground for the new tab. The presence of 'selected' property 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will override this default. 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool selected = true; 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (args->HasKey(keys::kSelectedKey)) 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kSelectedKey, 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &selected)); 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can't load extension URLs into incognito windows. Special case to 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fall back to a normal window. 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url.SchemeIs(chrome::kExtensionScheme) && 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->profile()->IsOffTheRecord()) { 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile = browser->profile()->GetOriginalProfile(); 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = BrowserList::FindBrowserWithType(profile, 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser::TYPE_NORMAL, false); 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) { 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = Browser::Create(profile); 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->window()->Show(); 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 616731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If index is specified, honor the value, but keep it bound to 617731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // -1 <= index <= tab_strip->count() where -1 invokes the default behavior. 618731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int index = -1; 619731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (args->HasKey(keys::kIndexKey)) 620731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kIndexKey, &index)); 621731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = browser->tabstrip_model(); 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 624731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick index = std::min(std::max(index, -1), tab_strip->count()); 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int add_types = selected ? TabStripModel::ADD_SELECTED : 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel::ADD_NONE; 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch add_types |= TabStripModel::ADD_FORCE_INDEX; 629731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Browser::AddTabWithURLParams params(url, PageTransition::LINK); 630731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick params.index = index; 631731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick params.add_types = add_types; 632731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick TabContents* contents = browser->AddTabWithURL(¶ms); 6333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick index = browser->tabstrip_model()->GetIndexOfTabContents(contents); 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selected) 636731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick contents->view()->SetInitialFocus(); 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return data about the newly created tab. 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_callback()) 6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick result_.reset(ExtensionTabUtil::CreateTabValue(contents, 6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick browser->tabstrip_model(), 6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick index)); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetTabFunction::RunImpl() { 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id; 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = NULL; 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = NULL; 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_index = -1; 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, &tab_strip, &contents, &tab_index, &error_)) 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents, tab_strip, 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_index)); 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetCurrentTabFunction::RunImpl() { 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(dispatcher()); 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = dispatcher()->delegate()->associated_tab_contents(); 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents) 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents)); 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UpdateTabFunction::RunImpl() { 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id; 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* update_props; 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* tab_strip = NULL; 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = NULL; 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_index = -1; 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, &tab_strip, &contents, &tab_index, &error_)) 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController& controller = contents->controller(); 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(rafaelw): handle setting remaining tab properties: 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // -title 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // -favIconUrl 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Navigate the tab to a new location if the url different. 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string url_string; 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kUrlKey)) { 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetString( 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kUrlKey, &url_string)); 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.is_valid()) { 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_string); 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // JavaScript URLs can do the same kinds of things as cross-origin XHR, so 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we need to check host permissions before allowing them. 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url.SchemeIs(chrome::kJavaScriptScheme)) { 708731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Extension* extension = GetExtension(); 709731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::vector<URLPattern> host_permissions = 710731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick extension->host_permissions(); 711731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!Extension::CanExecuteScriptOnPage( 712731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick contents->GetURL(), 713731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick extension->CanExecuteScriptEverywhere(), 714731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &host_permissions, 715731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NULL, 716731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &error_)) { 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 718731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(aa): How does controller queue URLs? Is there any chance that this 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // JavaScript URL will end up applying to something other than 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // controller->GetURL()? 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_strip->IsTabPinned(tab_index)) { 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't allow changing the url of pinned tabs. 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kCannotUpdatePinnedTab; 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller.LoadURL(url, GURL(), PageTransition::LINK); 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The URL of a tab contents never actually changes to a JavaScript URL, so 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this check only makes sense in other cases. 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.SchemeIs(chrome::kJavaScriptScheme)) 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(url.spec(), contents->GetURL().spec()); 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool selected = false; 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(rafaelw): Setting |selected| from js doesn't make much sense. 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Move tab selection management up to window. 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kSelectedKey)) { 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kSelectedKey, 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &selected)); 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selected) { 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_strip->selected_index() != tab_index) { 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_strip->SelectTabContentsAt(tab_index, false); 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(contents, tab_strip->GetSelectedTabContents()); 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents->Focus(); 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_callback()) 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents, tab_strip, 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_index)); 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MoveTabFunction::RunImpl() { 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id; 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* update_props; 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_index; 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kIndexKey, &new_index)); 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(new_index >= 0); 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* source_browser = NULL; 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* source_tab_strip = NULL; 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = NULL; 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_index = -1; 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &source_browser, &source_tab_strip, &contents, 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &tab_index, &error_)) 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (source_browser->type() != Browser::TYPE_NORMAL) { 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kCanOnlyMoveTabsWithinNormalWindowsError; 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_props->HasKey(keys::kWindowIdKey)) { 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* target_browser; 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id; 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kWindowIdKey, &window_id)); 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_browser = GetBrowserInProfileWithId(profile(), window_id, 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!target_browser) 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_browser->type() != Browser::TYPE_NORMAL) { 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kCanOnlyMoveTabsWithinNormalWindowsError; 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If windowId is different from the current window, move between windows. 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ExtensionTabUtil::GetWindowId(target_browser) != 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionTabUtil::GetWindowId(source_browser)) { 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel* target_tab_strip = target_browser->tabstrip_model(); 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents = source_tab_strip->DetachTabContentsAt(tab_index); 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) { 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 8093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kTabNotFoundError, base::IntToString(tab_id)); 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clamp move location to the last position. 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is ">" because it can append to a new index position. 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_index > target_tab_strip->count()) 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_index = target_tab_strip->count(); 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_tab_strip->InsertTabContentsAt(new_index, contents, 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel::ADD_NONE); 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_callback()) 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents, 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_tab_strip, new_index)); 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Perform a simple within-window move. 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clamp move location to the last position. 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is ">=" because the move must be to an existing location. 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_index >= source_tab_strip->count()) 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_index = source_tab_strip->count() - 1; 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_index != tab_index) 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch source_tab_strip->MoveTabContentsAt(tab_index, new_index, false); 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_callback()) 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(ExtensionTabUtil::CreateTabValue(contents, source_tab_strip, 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_index)); 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveTabFunction::RunImpl() { 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id; 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = NULL; 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = NULL; 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &browser, NULL, &contents, NULL, &error_)) 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Close the tab in this convoluted way, since there's a chance that the tab 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is being dragged, or we're in some other nested event loop. This code path 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should ensure that the tab is safely closed under such circumstances, 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // whereas |Browser::CloseTabContents()| does not. 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderViewHost* render_view_host = contents->render_view_host(); 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch render_view_host->delegate()->Close(render_view_host); 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CaptureVisibleTabFunction::RunImpl() { 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser; 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windowId defaults to "current" window. 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_id = -1; 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetBrowserInProfileWithId(profile(), window_id, 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), &error_); 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) { 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_format_ = FORMAT_JPEG; // Default format is JPEG. 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_quality_ = kDefaultQuality; // Default quality setting. 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(1)) { 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* options; 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options)); 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (options->HasKey(keys::kFormatKey)) { 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string format; 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE( 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options->GetString(keys::kFormatKey, &format)); 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (format == keys::kFormatValueJpeg) { 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_format_ = FORMAT_JPEG; 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (format == keys::kFormatValuePng) { 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_format_ = FORMAT_PNG; 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Schema validation should make this unreachable. 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(0); 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (options->HasKey(keys::kQualityKey)) { 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE( 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options->GetInteger(keys::kQualityKey, &image_quality_)); 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* tab_contents = browser->GetSelectedTabContents(); 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tab_contents) { 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kInternalVisibleTabCaptureError; 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderViewHost* render_view_host = tab_contents->render_view_host(); 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If a backing store is cached for the tab we want to capture, 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and it can be copied into a bitmap, then use it to generate the image. 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BackingStore* backing_store = render_view_host->GetBackingStore(false); 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (backing_store && CaptureSnapshotFromBackingStore(backing_store)) 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ask the renderer for a snapshot of the tab. 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch render_view_host->CaptureSnapshot(); 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::TAB_SNAPSHOT_TAKEN, 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // Balanced in CaptureVisibleTabFunction::Observe(). 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Build the image of a tab's contents out of a backing store. 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This may fail if we can not copy a backing store into a bitmap. 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For example, some uncommon X11 visual modes are not supported by 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CopyFromBackingStore(). 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CaptureVisibleTabFunction::CaptureSnapshotFromBackingStore( 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BackingStore* backing_store) { 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch skia::PlatformCanvas temp_canvas; 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!backing_store->CopyFromBackingStore(gfx::Rect(backing_store->size()), 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &temp_canvas)) { 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(INFO) << "captureVisibleTab() Got image from backing store."; 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResultFromBitmap( 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch temp_canvas.getTopPlatformDevice().accessBitmap(false)); 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// If a backing store was not available in CaptureVisibleTabFunction::RunImpl, 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// than the renderer was asked for a snapshot. Listen for a notification 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that the snapshot is available. 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CaptureVisibleTabFunction::Observe(NotificationType type, 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(type == NotificationType::TAB_SNAPSHOT_TAKEN); 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap *screen_capture = Details<const SkBitmap>(details).ptr(); 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool error = screen_capture->empty(); 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error) { 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kInternalVisibleTabCaptureError; 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(false); 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(INFO) << "captureVisibleTab() Got image from renderer."; 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResultFromBitmap(*screen_capture); 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // Balanced in CaptureVisibleTabFunction::RunImpl(). 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Turn a bitmap of the screen into an image, set that image as the result, 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// and call SendResponse(). 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CaptureVisibleTabFunction::SendResultFromBitmap( 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& screen_capture) { 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<RefCountedBytes> image_data(new RefCountedBytes); 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkAutoLockPixels screen_capture_lock(screen_capture); 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool encoded = false; 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string mime_type; 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (image_format_) { 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case FORMAT_JPEG: 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch encoded = gfx::JPEGCodec::Encode( 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<unsigned char*>(screen_capture.getAddr32(0, 0)), 986731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gfx::JPEGCodec::FORMAT_SkBitmap, 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_capture.width(), 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_capture.height(), 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(screen_capture.rowBytes()), 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_quality_, 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &image_data->data); 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type = keys::kMimeTypeJpeg; 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case FORMAT_PNG: 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch encoded = gfx::PNGCodec::EncodeBGRASkBitmap( 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch screen_capture, 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true, // Discard transparency. 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &image_data->data); 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type = keys::kMimeTypePng; 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Invalid image format."; 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!encoded) { 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage( 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch keys::kInternalVisibleTabCaptureError, ""); 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(false); 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string base64_result; 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string stream_as_string; 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_as_string.resize(image_data->data.size()); 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(&stream_as_string[0], 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const char*>(&image_data->data[0]), 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_data->data.size()); 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Base64Encode(stream_as_string, &base64_result); 10203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base64_result.insert(0, base::StringPrintf("data:%s;base64,", 10213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick mime_type.c_str())); 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(new StringValue(base64_result)); 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(true); 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DetectTabLanguageFunction::RunImpl() { 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id = 0; 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = NULL; 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = NULL; 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If |tab_id| is specified, look for it. Otherwise default to selected tab 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in the current window. 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HasOptionalArgument(0)) { 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetTabById(tab_id, profile(), include_incognito(), 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &browser, NULL, &contents, NULL, &error_)) { 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !contents) 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents = browser->tabstrip_model()->GetSelectedTabContents(); 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents) 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (contents->controller().needs_reload()) { 1051731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If the tab hasn't been loaded, don't wait for the tab to load. 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kCannotDetermineLanguageOfUnloadedTab; 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // Balanced in GotLanguage() 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!contents->language_state().original_language().empty()) { 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delay the callback invocation until after the current JS call has 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // returned. 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &DetectTabLanguageFunction::GotLanguage, 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents->language_state().original_language())); 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab contents does not know its language yet. Let's wait until it 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // receives it, or until the tab is closed/navigates to some other page. 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::TAB_LANGUAGE_DETERMINED, 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<TabContents>(contents)); 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::TAB_CLOSING, 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(&(contents->controller()))); 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<NavigationController>(&(contents->controller()))); 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DetectTabLanguageFunction::Observe(NotificationType type, 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string language; 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == NotificationType::TAB_LANGUAGE_DETERMINED) 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch language = *Details<std::string>(details).ptr(); 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.RemoveAll(); 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Call GotLanguage in all cases as we want to guarantee the callback is 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // called for every API call the extension made. 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GotLanguage(language); 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DetectTabLanguageFunction::GotLanguage(const std::string& language) { 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_.reset(Value::CreateStringValue(language.c_str())); 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(true); 1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // Balanced in Run() 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static helpers 1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic Browser* GetBrowserInProfileWithId(Profile* profile, 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int window_id, 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* error_message) { 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* incognito_profile = 11053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick include_incognito && profile->HasOffTheRecordProfile() ? 11063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick profile->GetOffTheRecordProfile() : NULL; 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BrowserList::const_iterator browser = BrowserList::begin(); 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser != BrowserList::end(); ++browser) { 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (((*browser)->profile() == profile || 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*browser)->profile() == incognito_profile) && 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionTabUtil::GetWindowId(*browser) == window_id) 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return *browser; 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error_message) 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *error_message = ExtensionErrorUtils::FormatErrorMessage( 11173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kWindowNotFoundError, base::IntToString(window_id)); 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool GetTabById(int tab_id, Profile* profile, 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool include_incognito, 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser** browser, 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripModel** tab_strip, 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents** contents, 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* tab_index, 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* error_message) { 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ExtensionTabUtil::GetTabById(tab_id, profile, include_incognito, 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser, tab_strip, contents, tab_index)) 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error_message) 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *error_message = ExtensionErrorUtils::FormatErrorMessage( 11353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick keys::kTabNotFoundError, base::IntToString(tab_id)); 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string GetWindowTypeText(Browser::Type type) { 1141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if ((type & Browser::TYPE_POPUP) == Browser::TYPE_POPUP) 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return keys::kWindowTypeValuePopup; 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if ((type & Browser::TYPE_APP) == Browser::TYPE_APP) 1145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return keys::kWindowTypeValueApp; 1146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(type == Browser::TYPE_NORMAL); 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return keys::kWindowTypeValueNormal; 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic GURL ResolvePossiblyRelativeURL(std::string url_string, 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Extension* extension) { 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url = GURL(url_string); 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url.is_valid()) 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url = extension->GetResourceURL(url_string); 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return url; 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1159