| Index: chrome/browser/extensions/api/tabs/tabs.cc | 
| =================================================================== | 
| --- chrome/browser/extensions/api/tabs/tabs.cc	(revision 176049) | 
| +++ chrome/browser/extensions/api/tabs/tabs.cc	(working copy) | 
| @@ -1,1886 +0,0 @@ | 
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| -// Use of this source code is governed by a BSD-style license that can be | 
| -// found in the LICENSE file. | 
| - | 
| -#include "chrome/browser/extensions/api/tabs/tabs.h" | 
| - | 
| -#include <algorithm> | 
| -#include <limits> | 
| -#include <vector> | 
| - | 
| -#include "base/base64.h" | 
| -#include "base/bind.h" | 
| -#include "base/command_line.h" | 
| -#include "base/logging.h" | 
| -#include "base/memory/ref_counted_memory.h" | 
| -#include "base/message_loop.h" | 
| -#include "base/stl_util.h" | 
| -#include "base/string16.h" | 
| -#include "base/string_number_conversions.h" | 
| -#include "base/string_util.h" | 
| -#include "base/stringprintf.h" | 
| -#include "base/utf_string_conversions.h" | 
| -#include "chrome/browser/extensions/api/tabs/tabs_constants.h" | 
| -#include "chrome/browser/extensions/extension_function_dispatcher.h" | 
| -#include "chrome/browser/extensions/extension_function_util.h" | 
| -#include "chrome/browser/extensions/extension_host.h" | 
| -#include "chrome/browser/extensions/extension_service.h" | 
| -#include "chrome/browser/extensions/extension_tab_util.h" | 
| -#include "chrome/browser/extensions/script_executor.h" | 
| -#include "chrome/browser/extensions/tab_helper.h" | 
| -#include "chrome/browser/extensions/window_controller.h" | 
| -#include "chrome/browser/extensions/window_controller_list.h" | 
| -#include "chrome/browser/prefs/incognito_mode_prefs.h" | 
| -#include "chrome/browser/prefs/pref_service.h" | 
| -#include "chrome/browser/profiles/profile.h" | 
| -#include "chrome/browser/translate/translate_tab_helper.h" | 
| -#include "chrome/browser/ui/browser.h" | 
| -#include "chrome/browser/ui/browser_commands.h" | 
| -#include "chrome/browser/ui/browser_finder.h" | 
| -#include "chrome/browser/ui/browser_list.h" | 
| -#include "chrome/browser/ui/browser_navigator.h" | 
| -#include "chrome/browser/ui/browser_tabstrip.h" | 
| -#include "chrome/browser/ui/browser_window.h" | 
| -#include "chrome/browser/ui/extensions/shell_window.h" | 
| -#include "chrome/browser/ui/host_desktop.h" | 
| -#include "chrome/browser/ui/panels/panel_manager.h" | 
| -#include "chrome/browser/ui/snapshot_tab_helper.h" | 
| -#include "chrome/browser/ui/tabs/tab_strip_model.h" | 
| -#include "chrome/browser/ui/window_sizer/window_sizer.h" | 
| -#include "chrome/browser/web_applications/web_app.h" | 
| -#include "chrome/common/chrome_notification_types.h" | 
| -#include "chrome/common/chrome_switches.h" | 
| -#include "chrome/common/extensions/api/windows.h" | 
| -#include "chrome/common/extensions/extension.h" | 
| -#include "chrome/common/extensions/extension_manifest_constants.h" | 
| -#include "chrome/common/extensions/extension_messages.h" | 
| -#include "chrome/common/extensions/user_script.h" | 
| -#include "chrome/common/pref_names.h" | 
| -#include "chrome/common/url_constants.h" | 
| -#include "content/public/browser/navigation_controller.h" | 
| -#include "content/public/browser/navigation_entry.h" | 
| -#include "content/public/browser/notification_details.h" | 
| -#include "content/public/browser/notification_source.h" | 
| -#include "content/public/browser/render_view_host.h" | 
| -#include "content/public/browser/render_widget_host_view.h" | 
| -#include "content/public/browser/web_contents.h" | 
| -#include "content/public/browser/web_contents_view.h" | 
| -#include "content/public/common/url_constants.h" | 
| -#include "extensions/common/constants.h" | 
| -#include "extensions/common/error_utils.h" | 
| -#include "skia/ext/image_operations.h" | 
| -#include "skia/ext/platform_canvas.h" | 
| -#include "third_party/skia/include/core/SkBitmap.h" | 
| -#include "ui/base/models/list_selection_model.h" | 
| -#include "ui/base/ui_base_types.h" | 
| -#include "ui/gfx/codec/jpeg_codec.h" | 
| -#include "ui/gfx/codec/png_codec.h" | 
| - | 
| -#if defined(OS_WIN) | 
| -#include "win8/util/win8_util.h" | 
| -#endif  // OS_WIN | 
| - | 
| -namespace Get = extensions::api::windows::Get; | 
| -namespace GetAll = extensions::api::windows::GetAll; | 
| -namespace GetCurrent = extensions::api::windows::GetCurrent; | 
| -namespace GetLastFocused = extensions::api::windows::GetLastFocused; | 
| -namespace errors = extension_manifest_errors; | 
| -namespace keys = extensions::tabs_constants; | 
| - | 
| -using content::NavigationController; | 
| -using content::NavigationEntry; | 
| -using content::OpenURLParams; | 
| -using content::Referrer; | 
| -using content::RenderViewHost; | 
| -using content::WebContents; | 
| -using extensions::ErrorUtils; | 
| -using extensions::ScriptExecutor; | 
| -using extensions::WindowController; | 
| -using extensions::WindowControllerList; | 
| - | 
| -const int CaptureVisibleTabFunction::kDefaultQuality = 90; | 
| - | 
| -namespace { | 
| - | 
| -// |error_message| can optionally be passed in a will be set with an appropriate | 
| -// message if the window cannot be found by id. | 
| -Browser* GetBrowserInProfileWithId(Profile* profile, | 
| -                                   const int window_id, | 
| -                                   bool include_incognito, | 
| -                                   std::string* error_message) { | 
| -  Profile* incognito_profile = | 
| -      include_incognito && profile->HasOffTheRecordProfile() ? | 
| -          profile->GetOffTheRecordProfile() : NULL; | 
| -  for (BrowserList::const_iterator browser = BrowserList::begin(); | 
| -       browser != BrowserList::end(); ++browser) { | 
| -    if (((*browser)->profile() == profile || | 
| -         (*browser)->profile() == incognito_profile) && | 
| -        ExtensionTabUtil::GetWindowId(*browser) == window_id && | 
| -        ((*browser)->window())) | 
| -      return *browser; | 
| -  } | 
| - | 
| -  if (error_message) | 
| -    *error_message = ErrorUtils::FormatErrorMessage( | 
| -        keys::kWindowNotFoundError, base::IntToString(window_id)); | 
| - | 
| -  return NULL; | 
| -} | 
| - | 
| -bool GetBrowserFromWindowID( | 
| -    UIThreadExtensionFunction* function, int window_id, Browser** browser) { | 
| -  if (window_id == extension_misc::kCurrentWindowId) { | 
| -    *browser = function->GetCurrentBrowser(); | 
| -    if (!(*browser) || !(*browser)->window()) { | 
| -      function->SetError(keys::kNoCurrentWindowError); | 
| -      return false; | 
| -    } | 
| -  } else { | 
| -    std::string error; | 
| -    *browser = GetBrowserInProfileWithId( | 
| -        function->profile(), window_id, function->include_incognito(), &error); | 
| -    if (!*browser) { | 
| -      function->SetError(error); | 
| -      return false; | 
| -    } | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool GetWindowFromWindowID(UIThreadExtensionFunction* function, | 
| -                           int window_id, | 
| -                           WindowController** controller) { | 
| -  if (window_id == extension_misc::kCurrentWindowId) { | 
| -    WindowController* extension_window_controller = | 
| -        function->dispatcher()->delegate()->GetExtensionWindowController(); | 
| -    // If there is a window controller associated with this extension, use that. | 
| -    if (extension_window_controller) { | 
| -      *controller = extension_window_controller; | 
| -    } else { | 
| -      // Otherwise get the focused or most recently added window. | 
| -      *controller = WindowControllerList::GetInstance()-> | 
| -          CurrentWindowForFunction(function); | 
| -    } | 
| -    if (!(*controller)) { | 
| -      function->SetError(keys::kNoCurrentWindowError); | 
| -      return false; | 
| -    } | 
| -  } else { | 
| -    *controller = WindowControllerList::GetInstance()-> | 
| -        FindWindowForFunctionById(function, window_id); | 
| -    if (!(*controller)) { | 
| -      function->SetError(ErrorUtils::FormatErrorMessage( | 
| -          keys::kWindowNotFoundError, base::IntToString(window_id))); | 
| -      return false; | 
| -    } | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -// |error_message| can optionally be passed in and will be set with an | 
| -// appropriate message if the tab cannot be found by id. | 
| -bool GetTabById(int tab_id, | 
| -                Profile* profile, | 
| -                bool include_incognito, | 
| -                Browser** browser, | 
| -                TabStripModel** tab_strip, | 
| -                content::WebContents** contents, | 
| -                int* tab_index, | 
| -                std::string* error_message) { | 
| -  if (ExtensionTabUtil::GetTabById(tab_id, profile, include_incognito, | 
| -                                   browser, tab_strip, contents, tab_index)) | 
| -    return true; | 
| - | 
| -  if (error_message) | 
| -    *error_message = ErrorUtils::FormatErrorMessage( | 
| -        keys::kTabNotFoundError, base::IntToString(tab_id)); | 
| - | 
| -  return false; | 
| -} | 
| - | 
| -// A three state enum to distinguish between when a boolean query argument is | 
| -// set or not. | 
| -enum QueryArg { | 
| -  NOT_SET = -1, | 
| -  MATCH_FALSE, | 
| -  MATCH_TRUE | 
| -}; | 
| - | 
| -bool MatchesQueryArg(QueryArg arg, bool value) { | 
| -  if (arg == NOT_SET) | 
| -    return true; | 
| - | 
| -  return (arg == MATCH_TRUE && value) || (arg == MATCH_FALSE && !value); | 
| -} | 
| - | 
| -QueryArg ParseBoolQueryArg(base::DictionaryValue* query, const char* key) { | 
| -  if (query->HasKey(key)) { | 
| -    bool value = false; | 
| -    CHECK(query->GetBoolean(key, &value)); | 
| -    return value ? MATCH_TRUE : MATCH_FALSE; | 
| -  } | 
| -  return NOT_SET; | 
| -} | 
| - | 
| -Browser* CreateBrowserWindow(const Browser::CreateParams& params, | 
| -                             Profile* profile, | 
| -                             const std::string& extension_id) { | 
| -  bool use_existing_browser_window = false; | 
| - | 
| -#if defined(OS_WIN) | 
| -  // In windows 8 metro mode we don't allow windows to be created. | 
| -  if (win8::IsSingleWindowMetroMode()) | 
| -    use_existing_browser_window = true; | 
| -#endif  // OS_WIN | 
| - | 
| -  Browser* new_window = NULL; | 
| -  if (use_existing_browser_window) | 
| -    // The false parameter passed below is to ensure that we find a browser | 
| -    // object matching the profile passed in, instead of the original profile | 
| -    new_window = chrome::FindTabbedBrowser(profile, false, | 
| -                                           params.host_desktop_type); | 
| - | 
| -  if (!new_window) | 
| -    new_window = new Browser(params); | 
| -  return new_window; | 
| -} | 
| - | 
| -}  // namespace | 
| - | 
| -// Windows --------------------------------------------------------------------- | 
| - | 
| -bool GetWindowFunction::RunImpl() { | 
| -  scoped_ptr<Get::Params> params(Get::Params::Create(*args_)); | 
| -  EXTENSION_FUNCTION_VALIDATE(params.get()); | 
| - | 
| -  bool populate_tabs = false; | 
| -  if (params->get_info.get() && params->get_info->populate.get()) | 
| -    populate_tabs = *params->get_info->populate; | 
| - | 
| -  WindowController* controller; | 
| -  if (!GetWindowFromWindowID(this, params->window_id, &controller)) | 
| -    return false; | 
| - | 
| -  if (populate_tabs) | 
| -    SetResult(controller->CreateWindowValueWithTabs(GetExtension())); | 
| -  else | 
| -    SetResult(controller->CreateWindowValue()); | 
| -  return true; | 
| -} | 
| - | 
| -bool GetCurrentWindowFunction::RunImpl() { | 
| -  scoped_ptr<GetCurrent::Params> params(GetCurrent::Params::Create(*args_)); | 
| -  EXTENSION_FUNCTION_VALIDATE(params.get()); | 
| - | 
| -  bool populate_tabs = false; | 
| -  if (params->get_info.get() && params->get_info->populate.get()) | 
| -    populate_tabs = *params->get_info->populate; | 
| - | 
| -  WindowController* controller; | 
| -  if (!GetWindowFromWindowID(this, | 
| -                             extension_misc::kCurrentWindowId, | 
| -                             &controller)) { | 
| -    return false; | 
| -  } | 
| -  if (populate_tabs) | 
| -    SetResult(controller->CreateWindowValueWithTabs(GetExtension())); | 
| -  else | 
| -    SetResult(controller->CreateWindowValue()); | 
| -  return true; | 
| -} | 
| - | 
| -bool GetLastFocusedWindowFunction::RunImpl() { | 
| -  scoped_ptr<GetLastFocused::Params> params( | 
| -      GetLastFocused::Params::Create(*args_)); | 
| -  EXTENSION_FUNCTION_VALIDATE(params.get()); | 
| - | 
| -  bool populate_tabs = false; | 
| -  if (params->get_info.get() && params->get_info->populate.get()) | 
| -    populate_tabs = *params->get_info->populate; | 
| - | 
| -  // Note: currently this returns the last active browser. If we decide to | 
| -  // include other window types (e.g. panels), we will need to add logic to | 
| -  // WindowControllerList that mirrors the active behavior of BrowserList. | 
| -  Browser* browser = chrome::FindAnyBrowser( | 
| -      profile(), include_incognito(), chrome::GetActiveDesktop()); | 
| -  if (!browser || !browser->window()) { | 
| -    error_ = keys::kNoLastFocusedWindowError; | 
| -    return false; | 
| -  } | 
| -  WindowController* controller = | 
| -      browser->extension_window_controller(); | 
| -  if (populate_tabs) | 
| -    SetResult(controller->CreateWindowValueWithTabs(GetExtension())); | 
| -  else | 
| -    SetResult(controller->CreateWindowValue()); | 
| -  return true; | 
| -} | 
| - | 
| -bool GetAllWindowsFunction::RunImpl() { | 
| -  scoped_ptr<GetAll::Params> params(GetAll::Params::Create(*args_)); | 
| -  EXTENSION_FUNCTION_VALIDATE(params.get()); | 
| - | 
| -  bool populate_tabs = false; | 
| -  if (params->get_info.get() && params->get_info->populate.get()) | 
| -    populate_tabs = *params->get_info->populate; | 
| - | 
| -  ListValue* window_list = new ListValue(); | 
| -  const WindowControllerList::ControllerList& windows = | 
| -      WindowControllerList::GetInstance()->windows(); | 
| -  for (WindowControllerList::ControllerList::const_iterator iter = | 
| -           windows.begin(); | 
| -       iter != windows.end(); ++iter) { | 
| -    if (!this->CanOperateOnWindow(*iter)) | 
| -      continue; | 
| -    if (populate_tabs) | 
| -      window_list->Append((*iter)->CreateWindowValueWithTabs(GetExtension())); | 
| -    else | 
| -      window_list->Append((*iter)->CreateWindowValue()); | 
| -  } | 
| -  SetResult(window_list); | 
| -  return true; | 
| -} | 
| - | 
| -bool CreateWindowFunction::ShouldOpenIncognitoWindow( | 
| -    const base::DictionaryValue* args, | 
| -    std::vector<GURL>* urls, | 
| -    bool* is_error) { | 
| -  *is_error = false; | 
| -  const IncognitoModePrefs::Availability incognito_availability = | 
| -      IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); | 
| -  bool incognito = false; | 
| -  if (args && args->HasKey(keys::kIncognitoKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kIncognitoKey, | 
| -                                                 &incognito)); | 
| -    if (incognito && incognito_availability == IncognitoModePrefs::DISABLED) { | 
| -      error_ = keys::kIncognitoModeIsDisabled; | 
| -      *is_error = true; | 
| -      return false; | 
| -    } | 
| -    if (!incognito && incognito_availability == IncognitoModePrefs::FORCED) { | 
| -      error_ = keys::kIncognitoModeIsForced; | 
| -      *is_error = true; | 
| -      return false; | 
| -    } | 
| -  } else if (incognito_availability == IncognitoModePrefs::FORCED) { | 
| -    // If incognito argument is not specified explicitly, we default to | 
| -    // incognito when forced so by policy. | 
| -    incognito = true; | 
| -  } | 
| - | 
| -  // Remove all URLs that are not allowed in an incognito session. Note that a | 
| -  // ChromeOS guest session is not considered incognito in this case. | 
| -  if (incognito && !profile_->IsGuestSession()) { | 
| -    std::string first_url_erased; | 
| -    for (size_t i = 0; i < urls->size();) { | 
| -      if (chrome::IsURLAllowedInIncognito((*urls)[i], profile())) { | 
| -        i++; | 
| -      } else { | 
| -        if (first_url_erased.empty()) | 
| -          first_url_erased = (*urls)[i].spec(); | 
| -        urls->erase(urls->begin() + i); | 
| -      } | 
| -    } | 
| -    if (urls->empty() && !first_url_erased.empty()) { | 
| -      error_ = ErrorUtils::FormatErrorMessage( | 
| -          keys::kURLsNotAllowedInIncognitoError, first_url_erased); | 
| -      *is_error = true; | 
| -      return false; | 
| -    } | 
| -  } | 
| -  return incognito; | 
| -} | 
| - | 
| -bool CreateWindowFunction::RunImpl() { | 
| -  DictionaryValue* args = NULL; | 
| -  std::vector<GURL> urls; | 
| -  WebContents* contents = NULL; | 
| - | 
| -  if (HasOptionalArgument(0)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); | 
| - | 
| -  // Look for optional url. | 
| -  if (args) { | 
| -    if (args->HasKey(keys::kUrlKey)) { | 
| -      Value* url_value; | 
| -      std::vector<std::string> url_strings; | 
| -      args->Get(keys::kUrlKey, &url_value); | 
| - | 
| -      // First, get all the URLs the client wants to open. | 
| -      if (url_value->IsType(Value::TYPE_STRING)) { | 
| -        std::string url_string; | 
| -        url_value->GetAsString(&url_string); | 
| -        url_strings.push_back(url_string); | 
| -      } else if (url_value->IsType(Value::TYPE_LIST)) { | 
| -        const ListValue* url_list = static_cast<const ListValue*>(url_value); | 
| -        for (size_t i = 0; i < url_list->GetSize(); ++i) { | 
| -          std::string url_string; | 
| -          EXTENSION_FUNCTION_VALIDATE(url_list->GetString(i, &url_string)); | 
| -          url_strings.push_back(url_string); | 
| -        } | 
| -      } | 
| - | 
| -      // Second, resolve, validate and convert them to GURLs. | 
| -      for (std::vector<std::string>::iterator i = url_strings.begin(); | 
| -           i != url_strings.end(); ++i) { | 
| -        GURL url = ExtensionTabUtil::ResolvePossiblyRelativeURL( | 
| -            *i, GetExtension()); | 
| -        if (!url.is_valid()) { | 
| -          error_ = ErrorUtils::FormatErrorMessage( | 
| -              keys::kInvalidUrlError, *i); | 
| -          return false; | 
| -        } | 
| -        // Don't let the extension crash the browser or renderers. | 
| -        if (ExtensionTabUtil::IsCrashURL(url)) { | 
| -          error_ = keys::kNoCrashBrowserError; | 
| -          return false; | 
| -        } | 
| -        urls.push_back(url); | 
| -      } | 
| -    } | 
| -  } | 
| - | 
| -  // Look for optional tab id. | 
| -  if (args) { | 
| -    int tab_id = -1; | 
| -    if (args->HasKey(keys::kTabIdKey)) { | 
| -      EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kTabIdKey, &tab_id)); | 
| - | 
| -      // Find the tab and detach it from the original window. | 
| -      TabStripModel* source_tab_strip = NULL; | 
| -      int tab_index = -1; | 
| -      if (!GetTabById(tab_id, profile(), include_incognito(), | 
| -                      NULL, &source_tab_strip, | 
| -                      NULL, &tab_index, &error_)) | 
| -        return false; | 
| -      contents = source_tab_strip->DetachWebContentsAt(tab_index); | 
| -      if (!contents) { | 
| -        error_ = ErrorUtils::FormatErrorMessage( | 
| -            keys::kTabNotFoundError, base::IntToString(tab_id)); | 
| -        return false; | 
| -      } | 
| -    } | 
| -  } | 
| - | 
| -  Profile* window_profile = profile(); | 
| -  Browser::Type window_type = Browser::TYPE_TABBED; | 
| - | 
| -  // panel_create_mode only applies if window is TYPE_PANEL. | 
| -  PanelManager::CreateMode panel_create_mode = PanelManager::CREATE_AS_DOCKED; | 
| - | 
| -  gfx::Rect window_bounds; | 
| -  bool focused = true; | 
| -  bool saw_focus_key = false; | 
| -  std::string extension_id; | 
| - | 
| -  // Decide whether we are opening a normal window or an incognito window. | 
| -  bool is_error = true; | 
| -  bool open_incognito_window = ShouldOpenIncognitoWindow(args, &urls, | 
| -                                                         &is_error); | 
| -  if (is_error) { | 
| -    // error_ member variable is set inside of ShouldOpenIncognitoWindow. | 
| -    return false; | 
| -  } | 
| -  if (open_incognito_window) { | 
| -    window_profile = window_profile->GetOffTheRecordProfile(); | 
| -  } | 
| - | 
| -  if (args) { | 
| -    // Figure out window type before figuring out bounds so that default | 
| -    // bounds can be set according to the window type. | 
| -    std::string type_str; | 
| -    if (args->HasKey(keys::kWindowTypeKey)) { | 
| -      EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kWindowTypeKey, | 
| -                                                  &type_str)); | 
| -      if (type_str == keys::kWindowTypeValuePopup) { | 
| -        window_type = Browser::TYPE_POPUP; | 
| -        extension_id = GetExtension()->id(); | 
| -      } else if (type_str == keys::kWindowTypeValuePanel || | 
| -                 type_str == keys::kWindowTypeValueDetachedPanel) { | 
| -        extension_id = GetExtension()->id(); | 
| -        bool use_panels = false; | 
| -#if !defined(OS_ANDROID) | 
| -        use_panels = PanelManager::ShouldUsePanels(extension_id); | 
| -#endif | 
| -        if (use_panels) { | 
| -          window_type = Browser::TYPE_PANEL; | 
| -#if !defined(OS_CHROMEOS) | 
| -          // Non-ChromeOS has both docked and detached panel types. | 
| -          if (type_str == keys::kWindowTypeValueDetachedPanel) | 
| -            panel_create_mode = PanelManager::CREATE_AS_DETACHED; | 
| -#endif | 
| -        } else { | 
| -          window_type = Browser::TYPE_POPUP; | 
| -        } | 
| -      } else if (type_str != keys::kWindowTypeValueNormal) { | 
| -        error_ = keys::kInvalidWindowTypeError; | 
| -        return false; | 
| -      } | 
| -    } | 
| - | 
| -    // Initialize default window bounds according to window type. | 
| -    // In ChromiumOS the default popup bounds is 0x0 which indicates default | 
| -    // window sizes in PanelBrowserView. In other OSs use the same default | 
| -    // bounds as windows. | 
| -#if !defined(OS_CHROMEOS) | 
| -    if (Browser::TYPE_TABBED == window_type || | 
| -        Browser::TYPE_POPUP == window_type) { | 
| -#else | 
| -    if (Browser::TYPE_TABBED == window_type) { | 
| -#endif | 
| -      // Try to position the new browser relative to its originating | 
| -      // browser window. The call offsets the bounds by kWindowTilePixels | 
| -      // (defined in WindowSizer to be 10). | 
| -      // | 
| -      // NOTE(rafaelw): It's ok if GetCurrentBrowser() returns NULL here. | 
| -      // GetBrowserWindowBounds will default to saved "default" values for | 
| -      // the app. | 
| -      ui::WindowShowState show_state = ui::SHOW_STATE_DEFAULT; | 
| -      WindowSizer::GetBrowserWindowBoundsAndShowState(std::string(), | 
| -                                                      gfx::Rect(), | 
| -                                                      GetCurrentBrowser(), | 
| -                                                      &window_bounds, | 
| -                                                      &show_state); | 
| -    } | 
| - | 
| -    if (Browser::TYPE_PANEL == window_type && | 
| -        PanelManager::CREATE_AS_DETACHED == panel_create_mode) { | 
| -      window_bounds.set_origin( | 
| -          PanelManager::GetInstance()->GetDefaultDetachedPanelOrigin()); | 
| -    } | 
| - | 
| -    // Any part of the bounds can optionally be set by the caller. | 
| -    int bounds_val = -1; | 
| -    if (args->HasKey(keys::kLeftKey)) { | 
| -      EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kLeftKey, | 
| -                                                   &bounds_val)); | 
| -      window_bounds.set_x(bounds_val); | 
| -    } | 
| - | 
| -    if (args->HasKey(keys::kTopKey)) { | 
| -      EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kTopKey, | 
| -                                                   &bounds_val)); | 
| -      window_bounds.set_y(bounds_val); | 
| -    } | 
| - | 
| -    if (args->HasKey(keys::kWidthKey)) { | 
| -      EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kWidthKey, | 
| -                                                   &bounds_val)); | 
| -      window_bounds.set_width(bounds_val); | 
| -    } | 
| - | 
| -    if (args->HasKey(keys::kHeightKey)) { | 
| -      EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kHeightKey, | 
| -                                                   &bounds_val)); | 
| -      window_bounds.set_height(bounds_val); | 
| -    } | 
| - | 
| -    if (args->HasKey(keys::kFocusedKey)) { | 
| -      EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kFocusedKey, | 
| -                                                   &focused)); | 
| -      saw_focus_key = true; | 
| -    } | 
| -  } | 
| - | 
| -#if !defined(OS_CHROMEOS) | 
| -  if (window_type == Browser::TYPE_PANEL) { | 
| -    std::string title = | 
| -        web_app::GenerateApplicationNameFromExtensionId(extension_id); | 
| -    // Note: Panels ignore all but the first url provided. | 
| -    Panel* panel = PanelManager::GetInstance()->CreatePanel( | 
| -        title, window_profile, urls[0], window_bounds, panel_create_mode); | 
| - | 
| -    // Unlike other window types, Panels do not take focus by default. | 
| -    if (!saw_focus_key || !focused) | 
| -      panel->ShowInactive(); | 
| -    else | 
| -      panel->Show(); | 
| - | 
| -    SetResult( | 
| -        panel->extension_window_controller()->CreateWindowValueWithTabs( | 
| -            GetExtension())); | 
| -    return true; | 
| -  } | 
| -#endif | 
| - | 
| -  // Create a new BrowserWindow. | 
| -  chrome::HostDesktopType host_desktop_type = chrome::GetActiveDesktop(); | 
| -  Browser::CreateParams create_params(window_type, window_profile, | 
| -                                      host_desktop_type); | 
| -  if (extension_id.empty()) { | 
| -    create_params.initial_bounds = window_bounds; | 
| -  } else { | 
| -    create_params = Browser::CreateParams::CreateForApp( | 
| -        window_type, | 
| -        web_app::GenerateApplicationNameFromExtensionId(extension_id), | 
| -        window_bounds, | 
| -        window_profile); | 
| -  } | 
| -  create_params.initial_show_state = ui::SHOW_STATE_NORMAL; | 
| -  create_params.host_desktop_type = chrome::GetActiveDesktop(); | 
| - | 
| -  Browser* new_window = CreateBrowserWindow(create_params, window_profile, | 
| -                                            extension_id); | 
| - | 
| -  for (std::vector<GURL>::iterator i = urls.begin(); i != urls.end(); ++i) { | 
| -    WebContents* tab = chrome::AddSelectedTabWithURL( | 
| -        new_window, *i, content::PAGE_TRANSITION_LINK); | 
| -    if (window_type == Browser::TYPE_PANEL) { | 
| -      extensions::TabHelper::FromWebContents(tab)-> | 
| -          SetExtensionAppIconById(extension_id); | 
| -    } | 
| -  } | 
| -  if (contents) { | 
| -    TabStripModel* target_tab_strip = new_window->tab_strip_model(); | 
| -    target_tab_strip->InsertWebContentsAt(urls.size(), contents, | 
| -                                          TabStripModel::ADD_NONE); | 
| -  } else if (urls.empty()) { | 
| -    chrome::NewTab(new_window); | 
| -  } | 
| -  chrome::SelectNumberedTab(new_window, 0); | 
| - | 
| -  // Unlike other window types, Panels do not take focus by default. | 
| -  if (!saw_focus_key && window_type == Browser::TYPE_PANEL) | 
| -    focused = false; | 
| - | 
| -  if (focused) | 
| -    new_window->window()->Show(); | 
| -  else | 
| -    new_window->window()->ShowInactive(); | 
| - | 
| -  if (new_window->profile()->IsOffTheRecord() && !include_incognito()) { | 
| -    // Don't expose incognito windows if the extension isn't allowed. | 
| -    SetResult(Value::CreateNullValue()); | 
| -  } else { | 
| -    SetResult( | 
| -        new_window->extension_window_controller()->CreateWindowValueWithTabs( | 
| -            GetExtension())); | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool UpdateWindowFunction::RunImpl() { | 
| -  int window_id = extension_misc::kUnknownWindowId; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); | 
| -  DictionaryValue* update_props; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); | 
| - | 
| -  WindowController* controller; | 
| -  if (!GetWindowFromWindowID(this, window_id, &controller)) | 
| -    return false; | 
| - | 
| -#if defined(OS_WIN) | 
| -  // Silently ignore changes on the window for metro mode. | 
| -  if (win8::IsSingleWindowMetroMode()) { | 
| -    SetResult(controller->CreateWindowValue()); | 
| -    return true; | 
| -  } | 
| -#endif | 
| - | 
| -  ui::WindowShowState show_state = ui::SHOW_STATE_DEFAULT;  // No change. | 
| -  std::string state_str; | 
| -  if (update_props->HasKey(keys::kShowStateKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetString(keys::kShowStateKey, | 
| -                                                        &state_str)); | 
| -    if (state_str == keys::kShowStateValueNormal) { | 
| -      show_state = ui::SHOW_STATE_NORMAL; | 
| -    } else if (state_str == keys::kShowStateValueMinimized) { | 
| -      show_state = ui::SHOW_STATE_MINIMIZED; | 
| -    } else if (state_str == keys::kShowStateValueMaximized) { | 
| -      show_state = ui::SHOW_STATE_MAXIMIZED; | 
| -    } else if (state_str == keys::kShowStateValueFullscreen) { | 
| -      show_state = ui::SHOW_STATE_FULLSCREEN; | 
| -    } else { | 
| -      error_ = keys::kInvalidWindowStateError; | 
| -      return false; | 
| -    } | 
| -  } | 
| - | 
| -  if (show_state != ui::SHOW_STATE_FULLSCREEN && | 
| -      show_state != ui::SHOW_STATE_DEFAULT) | 
| -    controller->SetFullscreenMode(false, GetExtension()->url()); | 
| - | 
| -  switch (show_state) { | 
| -    case ui::SHOW_STATE_MINIMIZED: | 
| -      controller->window()->Minimize(); | 
| -      break; | 
| -    case ui::SHOW_STATE_MAXIMIZED: | 
| -      controller->window()->Maximize(); | 
| -      break; | 
| -    case ui::SHOW_STATE_FULLSCREEN: | 
| -      if (controller->window()->IsMinimized() || | 
| -          controller->window()->IsMaximized()) | 
| -        controller->window()->Restore(); | 
| -      controller->SetFullscreenMode(true, GetExtension()->url()); | 
| -      break; | 
| -    case ui::SHOW_STATE_NORMAL: | 
| -      controller->window()->Restore(); | 
| -      break; | 
| -    default: | 
| -      break; | 
| -  } | 
| - | 
| -  gfx::Rect bounds; | 
| -  if (controller->window()->IsMinimized()) | 
| -    bounds = controller->window()->GetRestoredBounds(); | 
| -  else | 
| -    bounds = controller->window()->GetBounds(); | 
| -  bool set_bounds = false; | 
| - | 
| -  // Any part of the bounds can optionally be set by the caller. | 
| -  int bounds_val; | 
| -  if (update_props->HasKey(keys::kLeftKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( | 
| -        keys::kLeftKey, | 
| -        &bounds_val)); | 
| -    bounds.set_x(bounds_val); | 
| -    set_bounds = true; | 
| -  } | 
| - | 
| -  if (update_props->HasKey(keys::kTopKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( | 
| -        keys::kTopKey, | 
| -        &bounds_val)); | 
| -    bounds.set_y(bounds_val); | 
| -    set_bounds = true; | 
| -  } | 
| - | 
| -  if (update_props->HasKey(keys::kWidthKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( | 
| -        keys::kWidthKey, | 
| -        &bounds_val)); | 
| -    bounds.set_width(bounds_val); | 
| -    set_bounds = true; | 
| -  } | 
| - | 
| -  if (update_props->HasKey(keys::kHeightKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( | 
| -        keys::kHeightKey, | 
| -        &bounds_val)); | 
| -    bounds.set_height(bounds_val); | 
| -    set_bounds = true; | 
| -  } | 
| - | 
| -  if (set_bounds) { | 
| -    if (show_state == ui::SHOW_STATE_MINIMIZED || | 
| -        show_state == ui::SHOW_STATE_MAXIMIZED || | 
| -        show_state == ui::SHOW_STATE_FULLSCREEN) { | 
| -      error_ = keys::kInvalidWindowStateError; | 
| -      return false; | 
| -    } | 
| -    controller->window()->SetBounds(bounds); | 
| -  } | 
| - | 
| -  bool active_val = false; | 
| -  if (update_props->HasKey(keys::kFocusedKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 
| -        keys::kFocusedKey, &active_val)); | 
| -    if (active_val) { | 
| -      if (show_state == ui::SHOW_STATE_MINIMIZED) { | 
| -        error_ = keys::kInvalidWindowStateError; | 
| -        return false; | 
| -      } | 
| -      controller->window()->Activate(); | 
| -    } else { | 
| -      if (show_state == ui::SHOW_STATE_MAXIMIZED || | 
| -          show_state == ui::SHOW_STATE_FULLSCREEN) { | 
| -        error_ = keys::kInvalidWindowStateError; | 
| -        return false; | 
| -      } | 
| -      controller->window()->Deactivate(); | 
| -    } | 
| -  } | 
| - | 
| -  bool draw_attention = false; | 
| -  if (update_props->HasKey(keys::kDrawAttentionKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 
| -        keys::kDrawAttentionKey, &draw_attention)); | 
| -    controller->window()->FlashFrame(draw_attention); | 
| -  } | 
| - | 
| -  SetResult(controller->CreateWindowValue()); | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool RemoveWindowFunction::RunImpl() { | 
| -  int window_id = -1; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); | 
| - | 
| -  WindowController* controller; | 
| -  if (!GetWindowFromWindowID(this, window_id, &controller)) | 
| -    return false; | 
| - | 
| -#if defined(OS_WIN) | 
| -  // In Windows 8 metro mode, an existing Browser instance is reused for | 
| -  // hosting the extension tab. We should not be closing it as we don't own it. | 
| -  if (win8::IsSingleWindowMetroMode()) | 
| -    return false; | 
| -#endif | 
| - | 
| -  WindowController::Reason reason; | 
| -  if (!controller->CanClose(&reason)) { | 
| -    if (reason == WindowController::REASON_NOT_EDITABLE) | 
| -      error_ = keys::kTabStripNotEditableError; | 
| -    return false; | 
| -  } | 
| -  controller->window()->Close(); | 
| -  return true; | 
| -} | 
| - | 
| -// Tabs ------------------------------------------------------------------------ | 
| - | 
| -bool GetSelectedTabFunction::RunImpl() { | 
| -  // windowId defaults to "current" window. | 
| -  int window_id = extension_misc::kCurrentWindowId; | 
| - | 
| -  if (HasOptionalArgument(0)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); | 
| - | 
| -  Browser* browser = NULL; | 
| -  if (!GetBrowserFromWindowID(this, window_id, &browser)) | 
| -    return false; | 
| - | 
| -  TabStripModel* tab_strip = browser->tab_strip_model(); | 
| -  WebContents* contents = tab_strip->GetActiveWebContents(); | 
| -  if (!contents) { | 
| -    error_ = keys::kNoSelectedTabError; | 
| -    return false; | 
| -  } | 
| -  SetResult(ExtensionTabUtil::CreateTabValue(contents, | 
| -                                             tab_strip, | 
| -                                             tab_strip->active_index(), | 
| -                                             GetExtension())); | 
| -  return true; | 
| -} | 
| - | 
| -bool GetAllTabsInWindowFunction::RunImpl() { | 
| -  // windowId defaults to "current" window. | 
| -  int window_id = extension_misc::kCurrentWindowId; | 
| -  if (HasOptionalArgument(0)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); | 
| - | 
| -  Browser* browser = NULL; | 
| -  if (!GetBrowserFromWindowID(this, window_id, &browser)) | 
| -    return false; | 
| - | 
| -  SetResult(ExtensionTabUtil::CreateTabList(browser, GetExtension())); | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool QueryTabsFunction::RunImpl() { | 
| -  DictionaryValue* query = NULL; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query)); | 
| - | 
| -  QueryArg active = ParseBoolQueryArg(query, keys::kActiveKey); | 
| -  QueryArg pinned = ParseBoolQueryArg(query, keys::kPinnedKey); | 
| -  QueryArg selected = ParseBoolQueryArg(query, keys::kHighlightedKey); | 
| -  QueryArg current_window = ParseBoolQueryArg(query, keys::kCurrentWindowKey); | 
| -  QueryArg focused_window = | 
| -      ParseBoolQueryArg(query, keys::kLastFocusedWindowKey); | 
| - | 
| -  QueryArg loading = NOT_SET; | 
| -  if (query->HasKey(keys::kStatusKey)) { | 
| -    std::string status; | 
| -    EXTENSION_FUNCTION_VALIDATE(query->GetString(keys::kStatusKey, &status)); | 
| -    loading = (status == keys::kStatusValueLoading) ? MATCH_TRUE : MATCH_FALSE; | 
| -  } | 
| - | 
| -  // It is o.k. to use URLPattern::SCHEME_ALL here because this function does | 
| -  // not grant access to the content of the tabs, only to seeing their URLs and | 
| -  // meta data. | 
| -  URLPattern url_pattern(URLPattern::SCHEME_ALL, "<all_urls>"); | 
| -  if (query->HasKey(keys::kUrlKey)) { | 
| -    std::string value; | 
| -    EXTENSION_FUNCTION_VALIDATE(query->GetString(keys::kUrlKey, &value)); | 
| -    url_pattern = URLPattern(URLPattern::SCHEME_ALL, value); | 
| -  } | 
| - | 
| -  std::string title; | 
| -  if (query->HasKey(keys::kTitleKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE( | 
| -        query->GetString(keys::kTitleKey, &title)); | 
| - | 
| -  int window_id = extension_misc::kUnknownWindowId; | 
| -  if (query->HasKey(keys::kWindowIdKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE( | 
| -        query->GetInteger(keys::kWindowIdKey, &window_id)); | 
| - | 
| -  int index = -1; | 
| -  if (query->HasKey(keys::kIndexKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE( | 
| -        query->GetInteger(keys::kIndexKey, &index)); | 
| - | 
| -  std::string window_type; | 
| -  if (query->HasKey(keys::kWindowTypeLongKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE( | 
| -        query->GetString(keys::kWindowTypeLongKey, &window_type)); | 
| - | 
| -  ListValue* result = new ListValue(); | 
| -  for (BrowserList::const_iterator browser = BrowserList::begin(); | 
| -       browser != BrowserList::end(); ++browser) { | 
| -    if (!profile()->IsSameProfile((*browser)->profile())) | 
| -      continue; | 
| - | 
| -    if (!(*browser)->window()) | 
| -      continue; | 
| - | 
| -    if (!include_incognito() && profile() != (*browser)->profile()) | 
| -      continue; | 
| - | 
| -    if (window_id >= 0 && window_id != ExtensionTabUtil::GetWindowId(*browser)) | 
| -      continue; | 
| - | 
| -    if (window_id == extension_misc::kCurrentWindowId && | 
| -        *browser != GetCurrentBrowser()) | 
| -      continue; | 
| - | 
| -    if (!MatchesQueryArg(current_window, *browser == GetCurrentBrowser())) | 
| -      continue; | 
| - | 
| -    if (!MatchesQueryArg(focused_window, (*browser)->window()->IsActive())) | 
| -      continue; | 
| - | 
| -    if (!window_type.empty() && | 
| -        window_type != | 
| -        (*browser)->extension_window_controller()->GetWindowTypeText()) | 
| -      continue; | 
| - | 
| -    TabStripModel* tab_strip = (*browser)->tab_strip_model(); | 
| -    for (int i = 0; i < tab_strip->count(); ++i) { | 
| -      const WebContents* web_contents = tab_strip->GetWebContentsAt(i); | 
| - | 
| -      if (index > -1 && i != index) | 
| -        continue; | 
| - | 
| -      if (!MatchesQueryArg(selected, tab_strip->IsTabSelected(i))) | 
| -        continue; | 
| - | 
| -      if (!MatchesQueryArg(active, i == tab_strip->active_index())) | 
| -        continue; | 
| - | 
| -      if (!MatchesQueryArg(pinned, tab_strip->IsTabPinned(i))) | 
| -        continue; | 
| - | 
| -      if (!title.empty() && !MatchPattern(web_contents->GetTitle(), | 
| -                                          UTF8ToUTF16(title))) | 
| -        continue; | 
| - | 
| -      if (!url_pattern.MatchesURL(web_contents->GetURL())) | 
| -        continue; | 
| - | 
| -      if (!MatchesQueryArg(loading, web_contents->IsLoading())) | 
| -        continue; | 
| - | 
| -      result->Append(ExtensionTabUtil::CreateTabValue( | 
| -          web_contents, tab_strip, i, GetExtension())); | 
| -    } | 
| -  } | 
| - | 
| -  SetResult(result); | 
| -  return true; | 
| -} | 
| - | 
| -bool CreateTabFunction::RunImpl() { | 
| -  DictionaryValue* args = NULL; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args)); | 
| - | 
| -  // windowId defaults to "current" window. | 
| -  int window_id = extension_misc::kCurrentWindowId; | 
| -  if (args->HasKey(keys::kWindowIdKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args->GetInteger( | 
| -        keys::kWindowIdKey, &window_id)); | 
| - | 
| -  Browser* browser = NULL; | 
| -  if (!GetBrowserFromWindowID(this, window_id, &browser)) | 
| -    return false; | 
| - | 
| -  // Ensure the selected browser is tabbed. | 
| -  if (!browser->is_type_tabbed() && browser->IsAttemptingToCloseBrowser()) | 
| -    browser = chrome::FindTabbedBrowser(profile(), include_incognito(), | 
| -                                        browser->host_desktop_type()); | 
| - | 
| -  if (!browser || !browser->window()) | 
| -    return false; | 
| - | 
| -  // TODO(jstritar): Add a constant, chrome.tabs.TAB_ID_ACTIVE, that | 
| -  // represents the active tab. | 
| -  WebContents* opener = NULL; | 
| -  if (args->HasKey(keys::kOpenerTabIdKey)) { | 
| -    int opener_id = -1; | 
| -    EXTENSION_FUNCTION_VALIDATE(args->GetInteger( | 
| -        keys::kOpenerTabIdKey, &opener_id)); | 
| - | 
| -    if (!ExtensionTabUtil::GetTabById( | 
| -            opener_id, profile(), include_incognito(), | 
| -            NULL, NULL, &opener, NULL)) | 
| -      return false; | 
| -  } | 
| - | 
| -  // TODO(rafaelw): handle setting remaining tab properties: | 
| -  // -title | 
| -  // -favIconUrl | 
| - | 
| -  std::string url_string; | 
| -  GURL url; | 
| -  if (args->HasKey(keys::kUrlKey)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(args->GetString(keys::kUrlKey, | 
| -                                                &url_string)); | 
| -    url = ExtensionTabUtil::ResolvePossiblyRelativeURL(url_string, | 
| -                                                       GetExtension()); | 
| -    if (!url.is_valid()) { | 
| -      error_ = ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, | 
| -                                                       url_string); | 
| -      return false; | 
| -    } | 
| -  } | 
| - | 
| -  // Don't let extensions crash the browser or renderers. | 
| -  if (ExtensionTabUtil::IsCrashURL(url)) { | 
| -    error_ = keys::kNoCrashBrowserError; | 
| -    return false; | 
| -  } | 
| - | 
| -  // Default to foreground for the new tab. The presence of 'selected' property | 
| -  // will override this default. This property is deprecated ('active' should | 
| -  // be used instead). | 
| -  bool active = true; | 
| -  if (args->HasKey(keys::kSelectedKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kSelectedKey, &active)); | 
| - | 
| -  // The 'active' property has replaced the 'selected' property. | 
| -  if (args->HasKey(keys::kActiveKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kActiveKey, &active)); | 
| - | 
| -  // Default to not pinning the tab. Setting the 'pinned' property to true | 
| -  // will override this default. | 
| -  bool pinned = false; | 
| -  if (args->HasKey(keys::kPinnedKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args->GetBoolean(keys::kPinnedKey, &pinned)); | 
| - | 
| -  // We can't load extension URLs into incognito windows unless the extension | 
| -  // uses split mode. Special case to fall back to a tabbed window. | 
| -  if (url.SchemeIs(extensions::kExtensionScheme) && | 
| -      !GetExtension()->incognito_split_mode() && | 
| -      browser->profile()->IsOffTheRecord()) { | 
| -    Profile* profile = browser->profile()->GetOriginalProfile(); | 
| -    chrome::HostDesktopType desktop_type = browser->host_desktop_type(); | 
| - | 
| -    browser = chrome::FindTabbedBrowser(profile, false, desktop_type); | 
| -    if (!browser) { | 
| -      browser = new Browser(Browser::CreateParams(Browser::TYPE_TABBED, | 
| -                                                  profile, desktop_type)); | 
| -      browser->window()->Show(); | 
| -    } | 
| -  } | 
| - | 
| -  // If index is specified, honor the value, but keep it bound to | 
| -  // -1 <= index <= tab_strip->count() where -1 invokes the default behavior. | 
| -  int index = -1; | 
| -  if (args->HasKey(keys::kIndexKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args->GetInteger(keys::kIndexKey, &index)); | 
| - | 
| -  TabStripModel* tab_strip = browser->tab_strip_model(); | 
| - | 
| -  index = std::min(std::max(index, -1), tab_strip->count()); | 
| - | 
| -  int add_types = active ? TabStripModel::ADD_ACTIVE : | 
| -                             TabStripModel::ADD_NONE; | 
| -  add_types |= TabStripModel::ADD_FORCE_INDEX; | 
| -  if (pinned) | 
| -    add_types |= TabStripModel::ADD_PINNED; | 
| -  chrome::NavigateParams params(browser, url, content::PAGE_TRANSITION_LINK); | 
| -  params.disposition = active ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; | 
| -  params.tabstrip_index = index; | 
| -  params.tabstrip_add_types = add_types; | 
| -  chrome::Navigate(¶ms); | 
| - | 
| -  // The tab may have been created in a different window, so make sure we look | 
| -  // at the right tab strip. | 
| -  tab_strip = params.browser->tab_strip_model(); | 
| -  int new_index = tab_strip->GetIndexOfWebContents(params.target_contents); | 
| -  if (opener) | 
| -    tab_strip->SetOpenerOfWebContentsAt(new_index, opener); | 
| - | 
| -  if (active) | 
| -    params.target_contents->GetView()->SetInitialFocus(); | 
| - | 
| -  // Return data about the newly created tab. | 
| -  if (has_callback()) { | 
| -    SetResult(ExtensionTabUtil::CreateTabValue( | 
| -        params.target_contents, | 
| -        tab_strip, new_index, GetExtension())); | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool DuplicateTabFunction::RunImpl() { | 
| -  int tab_id = -1; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); | 
| - | 
| -  Browser* browser = NULL; | 
| -  TabStripModel* tab_strip = NULL; | 
| -  int tab_index = -1; | 
| -  if (!GetTabById(tab_id, profile(), include_incognito(), | 
| -                  &browser, &tab_strip, NULL, &tab_index, &error_)) { | 
| -    return false; | 
| -  } | 
| - | 
| -  WebContents* new_contents = chrome::DuplicateTabAt(browser, tab_index); | 
| -  if (!has_callback()) | 
| -    return true; | 
| - | 
| -  int new_index = tab_strip->GetIndexOfWebContents(new_contents); | 
| - | 
| -  // Return data about the newly created tab. | 
| -  SetResult(ExtensionTabUtil::CreateTabValue( | 
| -      new_contents, | 
| -      tab_strip, new_index, GetExtension())); | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool GetTabFunction::RunImpl() { | 
| -  int tab_id = -1; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); | 
| - | 
| -  TabStripModel* tab_strip = NULL; | 
| -  WebContents* contents = NULL; | 
| -  int tab_index = -1; | 
| -  if (!GetTabById(tab_id, profile(), include_incognito(), | 
| -                  NULL, &tab_strip, &contents, &tab_index, &error_)) | 
| -    return false; | 
| - | 
| -  SetResult(ExtensionTabUtil::CreateTabValue(contents, | 
| -                                             tab_strip, | 
| -                                             tab_index, | 
| -                                             GetExtension())); | 
| -  return true; | 
| -} | 
| - | 
| -bool GetCurrentTabFunction::RunImpl() { | 
| -  DCHECK(dispatcher()); | 
| - | 
| -  WebContents* contents = dispatcher()->delegate()->GetAssociatedWebContents(); | 
| -  if (contents) | 
| -    SetResult(ExtensionTabUtil::CreateTabValue(contents, GetExtension())); | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool HighlightTabsFunction::RunImpl() { | 
| -  DictionaryValue* info = NULL; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &info)); | 
| - | 
| -  // Get the window id from the params; default to current window if omitted. | 
| -  int window_id = extension_misc::kCurrentWindowId; | 
| -  if (info->HasKey(keys::kWindowIdKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE( | 
| -        info->GetInteger(keys::kWindowIdKey, &window_id)); | 
| - | 
| -  Browser* browser = NULL; | 
| -  if (!GetBrowserFromWindowID(this, window_id, &browser)) | 
| -    return false; | 
| - | 
| -  TabStripModel* tabstrip = browser->tab_strip_model(); | 
| -  ui::ListSelectionModel selection; | 
| -  int active_index = -1; | 
| - | 
| -  Value* tab_value = NULL; | 
| -  EXTENSION_FUNCTION_VALIDATE(info->Get(keys::kTabsKey, &tab_value)); | 
| - | 
| -  std::vector<int> tab_indices; | 
| -  EXTENSION_FUNCTION_VALIDATE(extensions::ReadOneOrMoreIntegers( | 
| -      tab_value, &tab_indices)); | 
| - | 
| -  // Create a new selection model as we read the list of tab indices. | 
| -  for (size_t i = 0; i < tab_indices.size(); ++i) { | 
| -    int index = tab_indices[i]; | 
| - | 
| -    // Make sure the index is in range. | 
| -    if (!tabstrip->ContainsIndex(index)) { | 
| -      error_ = ErrorUtils::FormatErrorMessage( | 
| -          keys::kTabIndexNotFoundError, base::IntToString(index)); | 
| -      return false; | 
| -    } | 
| - | 
| -    // By default, we make the first tab in the list active. | 
| -    if (active_index == -1) | 
| -      active_index = index; | 
| - | 
| -    selection.AddIndexToSelection(index); | 
| -  } | 
| - | 
| -  // Make sure they actually specified tabs to select. | 
| -  if (selection.empty()) { | 
| -    error_ = keys::kNoHighlightedTabError; | 
| -    return false; | 
| -  } | 
| - | 
| -  selection.set_active(active_index); | 
| -  browser->tab_strip_model()->SetSelectionFromModel(selection); | 
| -  SetResult( | 
| -      browser->extension_window_controller()->CreateWindowValueWithTabs( | 
| -          GetExtension())); | 
| -  return true; | 
| -} | 
| - | 
| -UpdateTabFunction::UpdateTabFunction() : web_contents_(NULL) { | 
| -} | 
| - | 
| -bool UpdateTabFunction::RunImpl() { | 
| -  DictionaryValue* update_props = NULL; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); | 
| - | 
| -  Value* tab_value = NULL; | 
| -  if (HasOptionalArgument(0)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 
| -  } | 
| - | 
| -  int tab_id = -1; | 
| -  WebContents* contents = NULL; | 
| -  if (tab_value == NULL || tab_value->IsType(Value::TYPE_NULL)) { | 
| -    Browser* browser = GetCurrentBrowser(); | 
| -    if (!browser) { | 
| -      error_ = keys::kNoCurrentWindowError; | 
| -      return false; | 
| -    } | 
| -    contents = browser->tab_strip_model()->GetActiveWebContents(); | 
| -    if (!contents) { | 
| -      error_ = keys::kNoSelectedTabError; | 
| -      return false; | 
| -    } | 
| -    tab_id = SessionID::IdForTab(contents); | 
| -  } else { | 
| -    EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); | 
| -  } | 
| - | 
| -  int tab_index = -1; | 
| -  TabStripModel* tab_strip = NULL; | 
| -  if (!GetTabById(tab_id, profile(), include_incognito(), | 
| -                  NULL, &tab_strip, &contents, &tab_index, &error_)) { | 
| -    return false; | 
| -  } | 
| - | 
| -  web_contents_ = contents; | 
| - | 
| -  // TODO(rafaelw): handle setting remaining tab properties: | 
| -  // -title | 
| -  // -favIconUrl | 
| - | 
| -  // Navigate the tab to a new location if the url is different. | 
| -  bool is_async = false; | 
| -  if (!UpdateURLIfPresent(update_props, tab_id, &is_async)) | 
| -    return false; | 
| - | 
| -  bool active = false; | 
| -  // TODO(rafaelw): Setting |active| from js doesn't make much sense. | 
| -  // Move tab selection management up to window. | 
| -  if (update_props->HasKey(keys::kSelectedKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 
| -        keys::kSelectedKey, &active)); | 
| - | 
| -  // The 'active' property has replaced 'selected'. | 
| -  if (update_props->HasKey(keys::kActiveKey)) | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 
| -        keys::kActiveKey, &active)); | 
| - | 
| -  if (active) { | 
| -    if (tab_strip->active_index() != tab_index) { | 
| -      tab_strip->ActivateTabAt(tab_index, false); | 
| -      DCHECK_EQ(contents, tab_strip->GetActiveWebContents()); | 
| -    } | 
| -    web_contents_->Focus(); | 
| -  } | 
| - | 
| -  if (update_props->HasKey(keys::kHighlightedKey)) { | 
| -    bool highlighted = false; | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 
| -        keys::kHighlightedKey, &highlighted)); | 
| -    if (highlighted != tab_strip->IsTabSelected(tab_index)) | 
| -      tab_strip->ToggleSelectionAt(tab_index); | 
| -  } | 
| - | 
| -  if (update_props->HasKey(keys::kPinnedKey)) { | 
| -    bool pinned = false; | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetBoolean( | 
| -        keys::kPinnedKey, &pinned)); | 
| -    tab_strip->SetTabPinned(tab_index, pinned); | 
| - | 
| -    // Update the tab index because it may move when being pinned. | 
| -    tab_index = tab_strip->GetIndexOfWebContents(contents); | 
| -  } | 
| - | 
| -  if (update_props->HasKey(keys::kOpenerTabIdKey)) { | 
| -    int opener_id = -1; | 
| -    EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( | 
| -        keys::kOpenerTabIdKey, &opener_id)); | 
| - | 
| -    WebContents* opener_contents = NULL; | 
| -    if (!ExtensionTabUtil::GetTabById( | 
| -            opener_id, profile(), include_incognito(), | 
| -            NULL, NULL, &opener_contents, NULL)) | 
| -      return false; | 
| - | 
| -    tab_strip->SetOpenerOfWebContentsAt(tab_index, opener_contents); | 
| -  } | 
| - | 
| -  if (!is_async) { | 
| -    PopulateResult(); | 
| -    SendResponse(true); | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool UpdateTabFunction::UpdateURLIfPresent(DictionaryValue* update_props, | 
| -                                           int tab_id, | 
| -                                           bool* is_async) { | 
| -  if (!update_props->HasKey(keys::kUrlKey)) | 
| -    return true; | 
| - | 
| -  std::string url_string; | 
| -  EXTENSION_FUNCTION_VALIDATE(update_props->GetString( | 
| -      keys::kUrlKey, &url_string)); | 
| -  GURL url = ExtensionTabUtil::ResolvePossiblyRelativeURL( | 
| -      url_string, GetExtension()); | 
| - | 
| -  if (!url.is_valid()) { | 
| -    error_ = ErrorUtils::FormatErrorMessage( | 
| -        keys::kInvalidUrlError, url_string); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Don't let the extension crash the browser or renderers. | 
| -  if (ExtensionTabUtil::IsCrashURL(url)) { | 
| -    error_ = keys::kNoCrashBrowserError; | 
| -    return false; | 
| -  } | 
| - | 
| -  // JavaScript URLs can do the same kinds of things as cross-origin XHR, so | 
| -  // we need to check host permissions before allowing them. | 
| -  if (url.SchemeIs(chrome::kJavaScriptScheme)) { | 
| -    if (!GetExtension()->CanExecuteScriptOnPage( | 
| -            web_contents_->GetURL(), | 
| -            web_contents_->GetURL(), | 
| -            tab_id, | 
| -            NULL, | 
| -            &error_)) { | 
| -      return false; | 
| -    } | 
| - | 
| -    extensions::TabHelper::FromWebContents(web_contents_)-> | 
| -        script_executor()->ExecuteScript( | 
| -            extension_id(), | 
| -            ScriptExecutor::JAVASCRIPT, | 
| -            url.path(), | 
| -            ScriptExecutor::TOP_FRAME, | 
| -            extensions::UserScript::DOCUMENT_IDLE, | 
| -            ScriptExecutor::MAIN_WORLD, | 
| -            base::Bind(&UpdateTabFunction::OnExecuteCodeFinished, this)); | 
| - | 
| -    *is_async = true; | 
| -    return true; | 
| -  } | 
| - | 
| -  web_contents_->GetController().LoadURL( | 
| -      url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); | 
| - | 
| -  // The URL of a tab contents never actually changes to a JavaScript URL, so | 
| -  // this check only makes sense in other cases. | 
| -  if (!url.SchemeIs(chrome::kJavaScriptScheme)) | 
| -    DCHECK_EQ(url.spec(), web_contents_->GetURL().spec()); | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -void UpdateTabFunction::PopulateResult() { | 
| -  if (!has_callback()) | 
| -    return; | 
| - | 
| -  SetResult(ExtensionTabUtil::CreateTabValue(web_contents_, GetExtension())); | 
| -} | 
| - | 
| -void UpdateTabFunction::OnExecuteCodeFinished(const std::string& error, | 
| -                                              int32 on_page_id, | 
| -                                              const GURL& url, | 
| -                                              const ListValue& script_result) { | 
| -  if (error.empty()) | 
| -    PopulateResult(); | 
| -  else | 
| -    error_ = error; | 
| -  SendResponse(error.empty()); | 
| -} | 
| - | 
| -bool MoveTabsFunction::RunImpl() { | 
| -  Value* tab_value = NULL; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 
| - | 
| -  std::vector<int> tab_ids; | 
| -  EXTENSION_FUNCTION_VALIDATE(extensions::ReadOneOrMoreIntegers( | 
| -      tab_value, &tab_ids)); | 
| - | 
| -  DictionaryValue* update_props = NULL; | 
| -  int new_index; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &update_props)); | 
| -  EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger(keys::kIndexKey, | 
| -      &new_index)); | 
| - | 
| -  ListValue tab_values; | 
| -  for (size_t i = 0; i < tab_ids.size(); ++i) { | 
| -    Browser* source_browser = NULL; | 
| -    TabStripModel* source_tab_strip = NULL; | 
| -    WebContents* contents = NULL; | 
| -    int tab_index = -1; | 
| -    if (!GetTabById(tab_ids[i], profile(), include_incognito(), | 
| -                    &source_browser, &source_tab_strip, &contents, | 
| -                    &tab_index, &error_)) | 
| -      return false; | 
| - | 
| -    // Don't let the extension move the tab if the user is dragging tabs. | 
| -    if (!source_browser->window()->IsTabStripEditable()) { | 
| -      error_ = keys::kTabStripNotEditableError; | 
| -      return false; | 
| -    } | 
| - | 
| -    // Insert the tabs one after another. | 
| -    new_index += i; | 
| - | 
| -    if (update_props->HasKey(keys::kWindowIdKey)) { | 
| -      Browser* target_browser = NULL; | 
| -      int window_id = extension_misc::kUnknownWindowId; | 
| -      EXTENSION_FUNCTION_VALIDATE(update_props->GetInteger( | 
| -          keys::kWindowIdKey, &window_id)); | 
| - | 
| -      if (!GetBrowserFromWindowID(this, window_id, &target_browser)) | 
| -        return false; | 
| - | 
| -      if (!target_browser->window()->IsTabStripEditable()) { | 
| -        error_ = keys::kTabStripNotEditableError; | 
| -        return false; | 
| -      } | 
| - | 
| -      if (!target_browser->is_type_tabbed()) { | 
| -        error_ = keys::kCanOnlyMoveTabsWithinNormalWindowsError; | 
| -        return false; | 
| -      } | 
| - | 
| -      if (target_browser->profile() != source_browser->profile()) { | 
| -        error_ = keys::kCanOnlyMoveTabsWithinSameProfileError; | 
| -        return false; | 
| -      } | 
| - | 
| -      // If windowId is different from the current window, move between windows. | 
| -      if (ExtensionTabUtil::GetWindowId(target_browser) != | 
| -          ExtensionTabUtil::GetWindowId(source_browser)) { | 
| -        TabStripModel* target_tab_strip = target_browser->tab_strip_model(); | 
| -        WebContents* web_contents = | 
| -            source_tab_strip->DetachWebContentsAt(tab_index); | 
| -        if (!web_contents) { | 
| -          error_ = ErrorUtils::FormatErrorMessage( | 
| -              keys::kTabNotFoundError, base::IntToString(tab_ids[i])); | 
| -          return false; | 
| -        } | 
| - | 
| -        // Clamp move location to the last position. | 
| -        // This is ">" because it can append to a new index position. | 
| -        // -1 means set the move location to the last position. | 
| -        if (new_index > target_tab_strip->count() || new_index < 0) | 
| -          new_index = target_tab_strip->count(); | 
| - | 
| -        target_tab_strip->InsertWebContentsAt( | 
| -            new_index, web_contents, TabStripModel::ADD_NONE); | 
| - | 
| -        if (has_callback()) { | 
| -          tab_values.Append(ExtensionTabUtil::CreateTabValue( | 
| -              web_contents, | 
| -              target_tab_strip, | 
| -              new_index, | 
| -              GetExtension())); | 
| -        } | 
| - | 
| -        continue; | 
| -      } | 
| -    } | 
| - | 
| -    // Perform a simple within-window move. | 
| -    // Clamp move location to the last position. | 
| -    // This is ">=" because the move must be to an existing location. | 
| -    // -1 means set the move location to the last position. | 
| -    if (new_index >= source_tab_strip->count() || new_index < 0) | 
| -      new_index = source_tab_strip->count() - 1; | 
| - | 
| -    if (new_index != tab_index) | 
| -      source_tab_strip->MoveWebContentsAt(tab_index, new_index, false); | 
| - | 
| -    if (has_callback()) { | 
| -      tab_values.Append(ExtensionTabUtil::CreateTabValue( | 
| -          contents, source_tab_strip, new_index, GetExtension())); | 
| -    } | 
| -  } | 
| - | 
| -  if (!has_callback()) | 
| -    return true; | 
| - | 
| -  // Only return the results as an array if there are multiple tabs. | 
| -  if (tab_ids.size() > 1) { | 
| -    SetResult(tab_values.DeepCopy()); | 
| -  } else if (tab_ids.size() == 1) { | 
| -    Value* value = NULL; | 
| -    CHECK(tab_values.Get(0, &value)); | 
| -    SetResult(value->DeepCopy()); | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool ReloadTabFunction::RunImpl() { | 
| -  bool bypass_cache = false; | 
| -  if (HasOptionalArgument(1)) { | 
| -      DictionaryValue* reload_props = NULL; | 
| -      EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &reload_props)); | 
| - | 
| -      if (reload_props->HasKey(keys::kBypassCache)) { | 
| -        EXTENSION_FUNCTION_VALIDATE(reload_props->GetBoolean( | 
| -            keys::kBypassCache, | 
| -            &bypass_cache)); | 
| -      } | 
| -  } | 
| - | 
| -  content::WebContents* web_contents = NULL; | 
| - | 
| -  // If |tab_id| is specified, look for it. Otherwise default to selected tab | 
| -  // in the current window. | 
| -  Value* tab_value = NULL; | 
| -  if (HasOptionalArgument(0)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 
| - | 
| -  if (tab_value == NULL || tab_value->IsType(Value::TYPE_NULL)) { | 
| -    Browser* browser = GetCurrentBrowser(); | 
| -    if (!browser) { | 
| -      error_ = keys::kNoCurrentWindowError; | 
| -      return false; | 
| -    } | 
| - | 
| -    if (!ExtensionTabUtil::GetDefaultTab(browser, &web_contents, NULL)) | 
| -      return false; | 
| -  } else { | 
| -    int tab_id = -1; | 
| -    EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&tab_id)); | 
| - | 
| -    Browser* browser = NULL; | 
| -    if (!GetTabById(tab_id, profile(), include_incognito(), | 
| -                    &browser, NULL, &web_contents, NULL, &error_)) | 
| -    return false; | 
| -  } | 
| - | 
| -  if (web_contents->ShowingInterstitialPage()) { | 
| -    // This does as same as Browser::ReloadInternal. | 
| -    NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); | 
| -    OpenURLParams params(entry->GetURL(), Referrer(), CURRENT_TAB, | 
| -                         content::PAGE_TRANSITION_RELOAD, false); | 
| -    GetCurrentBrowser()->OpenURL(params); | 
| -  } else if (bypass_cache) { | 
| -    web_contents->GetController().ReloadIgnoringCache(true); | 
| -  } else { | 
| -    web_contents->GetController().Reload(true); | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool RemoveTabsFunction::RunImpl() { | 
| -  Value* tab_value = NULL; | 
| -  EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 
| - | 
| -  std::vector<int> tab_ids; | 
| -  EXTENSION_FUNCTION_VALIDATE(extensions::ReadOneOrMoreIntegers( | 
| -      tab_value, &tab_ids)); | 
| - | 
| -  for (size_t i = 0; i < tab_ids.size(); ++i) { | 
| -    Browser* browser = NULL; | 
| -    WebContents* contents = NULL; | 
| -    if (!GetTabById(tab_ids[i], profile(), include_incognito(), | 
| -                    &browser, NULL, &contents, NULL, &error_)) | 
| -      return false; | 
| - | 
| -    // Don't let the extension remove a tab if the user is dragging tabs around. | 
| -    if (!browser->window()->IsTabStripEditable()) { | 
| -      error_ = keys::kTabStripNotEditableError; | 
| -      return false; | 
| -    } | 
| - | 
| -    // There's a chance that the tab is being dragged, or we're in some other | 
| -    // nested event loop. This code path ensures that the tab is safely closed | 
| -    // under such circumstances, whereas |TabStripModel::CloseWebContentsAt()| | 
| -    // does not. | 
| -    contents->Close(); | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool CaptureVisibleTabFunction::GetTabToCapture(WebContents** web_contents) { | 
| -  Browser* browser = NULL; | 
| -  // windowId defaults to "current" window. | 
| -  int window_id = extension_misc::kCurrentWindowId; | 
| - | 
| -  if (HasOptionalArgument(0)) | 
| -    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &window_id)); | 
| - | 
| -  if (!GetBrowserFromWindowID(this, window_id, &browser)) | 
| -    return false; | 
| - | 
| -  *web_contents = chrome::GetActiveWebContents(browser); | 
| -  if (*web_contents == NULL) { | 
| -    error_ = keys::kInternalVisibleTabCaptureError; | 
| -    return false; | 
| -  } | 
| - | 
| -  return true; | 
| -}; | 
| - | 
| -bool CaptureVisibleTabFunction::RunImpl() { | 
| -  PrefServiceBase* service = profile()->GetPrefs(); | 
| -  if (service->GetBoolean(prefs::kDisableScreenshots)) { | 
| -    error_ = keys::kScreenshotsDisabled; | 
| -    return false; | 
| -  } | 
| - | 
| -  WebContents* web_contents = NULL; | 
| -  if (!GetTabToCapture(&web_contents)) | 
| -    return false; | 
| - | 
| -  image_format_ = FORMAT_JPEG;  // Default format is JPEG. | 
| -  image_quality_ = kDefaultQuality;  // Default quality setting. | 
| - | 
| -  if (HasOptionalArgument(1)) { | 
| -    DictionaryValue* options = NULL; | 
| -    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options)); | 
| - | 
| -    if (options->HasKey(keys::kFormatKey)) { | 
| -      std::string format; | 
| -      EXTENSION_FUNCTION_VALIDATE( | 
| -          options->GetString(keys::kFormatKey, &format)); | 
| - | 
| -      if (format == keys::kFormatValueJpeg) { | 
| -        image_format_ = FORMAT_JPEG; | 
| -      } else if (format == keys::kFormatValuePng) { | 
| -        image_format_ = FORMAT_PNG; | 
| -      } else { | 
| -        // Schema validation should make this unreachable. | 
| -        EXTENSION_FUNCTION_VALIDATE(0); | 
| -      } | 
| -    } | 
| - | 
| -    if (options->HasKey(keys::kQualityKey)) { | 
| -      EXTENSION_FUNCTION_VALIDATE( | 
| -          options->GetInteger(keys::kQualityKey, &image_quality_)); | 
| -    } | 
| -  } | 
| - | 
| -  // captureVisibleTab() can return an image containing sensitive information | 
| -  // that the browser would otherwise protect.  Ensure the extension has | 
| -  // permission to do this. | 
| -  if (!GetExtension()->CanCaptureVisiblePage( | 
| -        web_contents->GetURL(), | 
| -        SessionID::IdForTab(web_contents), | 
| -        &error_)) { | 
| -    return false; | 
| -  } | 
| - | 
| -  RenderViewHost* render_view_host = web_contents->GetRenderViewHost(); | 
| -  content::RenderWidgetHostView* view = render_view_host->GetView(); | 
| -  if (!view) { | 
| -    error_ = keys::kInternalVisibleTabCaptureError; | 
| -    return false; | 
| -  } | 
| -  skia::PlatformBitmap* temp_bitmap = new skia::PlatformBitmap; | 
| -  render_view_host->CopyFromBackingStore( | 
| -      gfx::Rect(), | 
| -      view->GetViewBounds().size(), | 
| -      base::Bind(&CaptureVisibleTabFunction::CopyFromBackingStoreComplete, | 
| -                 this, | 
| -                 base::Owned(temp_bitmap)), | 
| -      temp_bitmap); | 
| -  return true; | 
| -} | 
| - | 
| -void CaptureVisibleTabFunction::CopyFromBackingStoreComplete( | 
| -    skia::PlatformBitmap* bitmap, | 
| -    bool succeeded) { | 
| -  if (succeeded) { | 
| -    VLOG(1) << "captureVisibleTab() got image from backing store."; | 
| -    SendResultFromBitmap(bitmap->GetBitmap()); | 
| -    return; | 
| -  } | 
| - | 
| -  WebContents* web_contents = NULL; | 
| -  if (!GetTabToCapture(&web_contents)) { | 
| -    error_ = keys::kInternalVisibleTabCaptureError; | 
| -    SendResponse(false); | 
| -    return; | 
| -  } | 
| - | 
| -  // Ask the renderer for a snapshot of the tab. | 
| -  registrar_.Add(this, | 
| -                 chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN, | 
| -                 content::Source<WebContents>(web_contents)); | 
| -  AddRef();  // Balanced in CaptureVisibleTabFunction::Observe(). | 
| -  SnapshotTabHelper::FromWebContents(web_contents)->CaptureSnapshot(); | 
| -} | 
| - | 
| -// If a backing store was not available in CaptureVisibleTabFunction::RunImpl, | 
| -// than the renderer was asked for a snapshot.  Listen for a notification | 
| -// that the snapshot is available. | 
| -void CaptureVisibleTabFunction::Observe( | 
| -    int type, | 
| -    const content::NotificationSource& source, | 
| -    const content::NotificationDetails& details) { | 
| -  DCHECK(type == chrome::NOTIFICATION_TAB_SNAPSHOT_TAKEN); | 
| - | 
| -  const SkBitmap *screen_capture = | 
| -      content::Details<const SkBitmap>(details).ptr(); | 
| -  const bool error = screen_capture->empty(); | 
| - | 
| -  if (error) { | 
| -    error_ = keys::kInternalVisibleTabCaptureError; | 
| -    SendResponse(false); | 
| -  } else { | 
| -    VLOG(1) << "captureVisibleTab() got image from renderer."; | 
| -    SendResultFromBitmap(*screen_capture); | 
| -  } | 
| - | 
| -  Release();  // Balanced in CaptureVisibleTabFunction::RunImpl(). | 
| -} | 
| - | 
| -// Turn a bitmap of the screen into an image, set that image as the result, | 
| -// and call SendResponse(). | 
| -void CaptureVisibleTabFunction::SendResultFromBitmap( | 
| -    const SkBitmap& screen_capture) { | 
| -  std::vector<unsigned char> data; | 
| -  SkAutoLockPixels screen_capture_lock(screen_capture); | 
| -  bool encoded = false; | 
| -  std::string mime_type; | 
| -  switch (image_format_) { | 
| -    case FORMAT_JPEG: | 
| -      encoded = gfx::JPEGCodec::Encode( | 
| -          reinterpret_cast<unsigned char*>(screen_capture.getAddr32(0, 0)), | 
| -          gfx::JPEGCodec::FORMAT_SkBitmap, | 
| -          screen_capture.width(), | 
| -          screen_capture.height(), | 
| -          static_cast<int>(screen_capture.rowBytes()), | 
| -          image_quality_, | 
| -          &data); | 
| -      mime_type = keys::kMimeTypeJpeg; | 
| -      break; | 
| -    case FORMAT_PNG: | 
| -      encoded = gfx::PNGCodec::EncodeBGRASkBitmap( | 
| -          screen_capture, | 
| -          true,  // Discard transparency. | 
| -          &data); | 
| -      mime_type = keys::kMimeTypePng; | 
| -      break; | 
| -    default: | 
| -      NOTREACHED() << "Invalid image format."; | 
| -  } | 
| - | 
| -  if (!encoded) { | 
| -    error_ = keys::kInternalVisibleTabCaptureError; | 
| -    SendResponse(false); | 
| -    return; | 
| -  } | 
| - | 
| -  std::string base64_result; | 
| -  base::StringPiece stream_as_string( | 
| -      reinterpret_cast<const char*>(vector_as_array(&data)), data.size()); | 
| - | 
| -  base::Base64Encode(stream_as_string, &base64_result); | 
| -  base64_result.insert(0, base::StringPrintf("data:%s;base64,", | 
| -                                             mime_type.c_str())); | 
| -  SetResult(new StringValue(base64_result)); | 
| -  SendResponse(true); | 
| -} | 
| - | 
| -void CaptureVisibleTabFunction::RegisterUserPrefs( | 
| -    PrefServiceSyncable* service) { | 
| -  service->RegisterBooleanPref(prefs::kDisableScreenshots, false, | 
| -                               PrefServiceSyncable::UNSYNCABLE_PREF); | 
| -} | 
| - | 
| -bool DetectTabLanguageFunction::RunImpl() { | 
| -  int tab_id = 0; | 
| -  Browser* browser = NULL; | 
| -  WebContents* contents = NULL; | 
| - | 
| -  // If |tab_id| is specified, look for it. Otherwise default to selected tab | 
| -  // in the current window. | 
| -  if (HasOptionalArgument(0)) { | 
| -    EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id)); | 
| -    if (!GetTabById(tab_id, profile(), include_incognito(), | 
| -                    &browser, NULL, &contents, NULL, &error_)) { | 
| -      return false; | 
| -    } | 
| -    if (!browser || !contents) | 
| -      return false; | 
| -  } else { | 
| -    browser = GetCurrentBrowser(); | 
| -    if (!browser) | 
| -      return false; | 
| -    contents = browser->tab_strip_model()->GetActiveWebContents(); | 
| -    if (!contents) | 
| -      return false; | 
| -  } | 
| - | 
| -  if (contents->GetController().NeedsReload()) { | 
| -    // If the tab hasn't been loaded, don't wait for the tab to load. | 
| -    error_ = keys::kCannotDetermineLanguageOfUnloadedTab; | 
| -    return false; | 
| -  } | 
| - | 
| -  AddRef();  // Balanced in GotLanguage(). | 
| - | 
| -  TranslateTabHelper* translate_tab_helper = | 
| -      TranslateTabHelper::FromWebContents(contents); | 
| -  if (!translate_tab_helper->language_state().original_language().empty()) { | 
| -    // Delay the callback invocation until after the current JS call has | 
| -    // returned. | 
| -    MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 
| -        &DetectTabLanguageFunction::GotLanguage, this, | 
| -        translate_tab_helper->language_state().original_language())); | 
| -    return true; | 
| -  } | 
| -  // The tab contents does not know its language yet.  Let's wait until it | 
| -  // receives it, or until the tab is closed/navigates to some other page. | 
| -  registrar_.Add(this, chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, | 
| -                 content::Source<WebContents>(contents)); | 
| -  registrar_.Add( | 
| -      this, chrome::NOTIFICATION_TAB_CLOSING, | 
| -      content::Source<NavigationController>(&(contents->GetController()))); | 
| -  registrar_.Add( | 
| -      this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 
| -      content::Source<NavigationController>(&(contents->GetController()))); | 
| -  return true; | 
| -} | 
| - | 
| -void DetectTabLanguageFunction::Observe( | 
| -    int type, | 
| -    const content::NotificationSource& source, | 
| -    const content::NotificationDetails& details) { | 
| -  std::string language; | 
| -  if (type == chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED) | 
| -    language = *content::Details<std::string>(details).ptr(); | 
| - | 
| -  registrar_.RemoveAll(); | 
| - | 
| -  // Call GotLanguage in all cases as we want to guarantee the callback is | 
| -  // called for every API call the extension made. | 
| -  GotLanguage(language); | 
| -} | 
| - | 
| -void DetectTabLanguageFunction::GotLanguage(const std::string& language) { | 
| -  SetResult(Value::CreateStringValue(language.c_str())); | 
| -  SendResponse(true); | 
| - | 
| -  Release();  // Balanced in Run() | 
| -} | 
|  |