Home | History | Annotate | Download | only in ui
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/browser_window_state.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/prefs/pref_service.h"
      9 #include "base/prefs/scoped_user_pref_update.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "chrome/browser/defaults.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/browser/sessions/session_service.h"
     14 #include "chrome/browser/sessions/session_service_factory.h"
     15 #include "chrome/browser/ui/browser.h"
     16 #include "chrome/browser/ui/window_sizer/window_sizer.h"
     17 #include "chrome/common/chrome_switches.h"
     18 #include "chrome/common/pref_names.h"
     19 
     20 namespace chrome {
     21 namespace {
     22 
     23 // Parse two comma-separated integers from str. Return true on success.
     24 bool ParseCommaSeparatedIntegers(const std::string& str,
     25                                  int* ret_num1,
     26                                  int* ret_num2) {
     27   size_t num1_size = str.find_first_of(',');
     28   if (num1_size == std::string::npos)
     29     return false;
     30 
     31   size_t num2_pos = num1_size + 1;
     32   size_t num2_size = str.size() - num2_pos;
     33   int num1 = 0;
     34   int num2 = 0;
     35   if (!base::StringToInt(str.substr(0, num1_size), &num1) ||
     36       !base::StringToInt(str.substr(num2_pos, num2_size), &num2))
     37     return false;
     38 
     39   *ret_num1 = num1;
     40   *ret_num2 = num2;
     41   return true;
     42 }
     43 
     44 class WindowPlacementPrefUpdate : public DictionaryPrefUpdate {
     45  public:
     46   WindowPlacementPrefUpdate(PrefService* service,
     47                             const std::string& window_name)
     48       : DictionaryPrefUpdate(service, prefs::kAppWindowPlacement),
     49         window_name_(window_name) {}
     50 
     51   virtual ~WindowPlacementPrefUpdate() {}
     52 
     53   virtual base::DictionaryValue* Get() OVERRIDE {
     54     base::DictionaryValue* all_apps_dict = DictionaryPrefUpdate::Get();
     55     base::DictionaryValue* this_app_dict = NULL;
     56     if (!all_apps_dict->GetDictionary(window_name_, &this_app_dict)) {
     57       this_app_dict = new base::DictionaryValue;
     58       all_apps_dict->Set(window_name_, this_app_dict);
     59     }
     60     return this_app_dict;
     61   }
     62 
     63  private:
     64   const std::string window_name_;
     65 
     66   DISALLOW_COPY_AND_ASSIGN(WindowPlacementPrefUpdate);
     67 };
     68 
     69 }  // namespace
     70 
     71 std::string GetWindowName(const Browser* browser) {
     72   if (browser->app_name().empty()) {
     73     return browser->is_type_popup() ?
     74         prefs::kBrowserWindowPlacementPopup : prefs::kBrowserWindowPlacement;
     75   }
     76   return browser->app_name();
     77 }
     78 
     79 scoped_ptr<DictionaryPrefUpdate> GetWindowPlacementDictionaryReadWrite(
     80     const std::string& window_name,
     81     PrefService* prefs) {
     82   DCHECK(!window_name.empty());
     83   // A normal DictionaryPrefUpdate will suffice for non-app windows.
     84   if (prefs->FindPreference(window_name.c_str())) {
     85     return make_scoped_ptr(
     86         new DictionaryPrefUpdate(prefs, window_name.c_str()));
     87   }
     88   return scoped_ptr<DictionaryPrefUpdate>(
     89       new WindowPlacementPrefUpdate(prefs, window_name));
     90 }
     91 
     92 const base::DictionaryValue* GetWindowPlacementDictionaryReadOnly(
     93     const std::string& window_name,
     94     PrefService* prefs) {
     95   DCHECK(!window_name.empty());
     96   if (prefs->FindPreference(window_name.c_str()))
     97     return prefs->GetDictionary(window_name.c_str());
     98 
     99   const base::DictionaryValue* app_windows =
    100       prefs->GetDictionary(prefs::kAppWindowPlacement);
    101   if (!app_windows)
    102     return NULL;
    103   const base::DictionaryValue* to_return = NULL;
    104   app_windows->GetDictionary(window_name, &to_return);
    105   return to_return;
    106 }
    107 
    108 bool ShouldSaveWindowPlacement(const Browser* browser) {
    109   // Only save the window placement of popups if the window is from a trusted
    110   // source (v1 app, devtools, or system window).
    111   return (browser->type() == Browser::TYPE_TABBED) ||
    112     ((browser->type() == Browser::TYPE_POPUP) && browser->is_trusted_source());
    113 }
    114 
    115 void SaveWindowPlacement(const Browser* browser,
    116                          const gfx::Rect& bounds,
    117                          ui::WindowShowState show_state) {
    118   // Save to the session storage service, used when reloading a past session.
    119   // Note that we don't want to be the ones who cause lazy initialization of
    120   // the session service. This function gets called during initial window
    121   // showing, and we don't want to bring in the session service this early.
    122   SessionService* session_service =
    123       SessionServiceFactory::GetForProfileIfExisting(browser->profile());
    124   if (session_service)
    125     session_service->SetWindowBounds(browser->session_id(), bounds, show_state);
    126 }
    127 
    128 void GetSavedWindowBoundsAndShowState(const Browser* browser,
    129                                       gfx::Rect* bounds,
    130                                       ui::WindowShowState* show_state) {
    131   DCHECK(browser);
    132   DCHECK(bounds);
    133   DCHECK(show_state);
    134   *bounds = browser->override_bounds();
    135   WindowSizer::GetBrowserWindowBoundsAndShowState(browser->app_name(),
    136                                                   *bounds,
    137                                                   browser,
    138                                                   bounds,
    139                                                   show_state);
    140 
    141   const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
    142   bool record_mode = parsed_command_line.HasSwitch(switches::kRecordMode);
    143   bool playback_mode = parsed_command_line.HasSwitch(switches::kPlaybackMode);
    144   if (record_mode || playback_mode) {
    145     // In playback/record mode we always fix the size of the browser and
    146     // move it to (0,0).  The reason for this is two reasons:  First we want
    147     // resize/moves in the playback to still work, and Second we want
    148     // playbacks to work (as much as possible) on machines w/ different
    149     // screen sizes.
    150     *bounds = gfx::Rect(0, 0, 800, 600);
    151   }
    152 
    153   // The following options override playback/record.
    154   if (parsed_command_line.HasSwitch(switches::kWindowSize)) {
    155     std::string str =
    156         parsed_command_line.GetSwitchValueASCII(switches::kWindowSize);
    157     int width, height;
    158     if (ParseCommaSeparatedIntegers(str, &width, &height))
    159       bounds->set_size(gfx::Size(width, height));
    160   }
    161   if (parsed_command_line.HasSwitch(switches::kWindowPosition)) {
    162     std::string str =
    163         parsed_command_line.GetSwitchValueASCII(switches::kWindowPosition);
    164     int x, y;
    165     if (ParseCommaSeparatedIntegers(str, &x, &y))
    166       bounds->set_origin(gfx::Point(x, y));
    167   }
    168 }
    169 
    170 }  // namespace chrome
    171