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 20namespace chrome { 21namespace { 22 23// Parse two comma-separated integers from str. Return true on success. 24bool 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 44class 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 71std::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 79scoped_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 92const 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 108bool 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 115void 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 128void 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