15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window_state.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/prefs/scoped_user_pref_update.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/defaults.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service_factory.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/window_sizer/window_sizer.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parse two comma-separated integers from str. Return true on success. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseCommaSeparatedIntegers(const std::string& str, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* ret_num1, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* ret_num2) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t num1_size = str.find_first_of(','); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num1_size == std::string::npos) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t num2_pos = num1_size + 1; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t num2_size = str.size() - num2_pos; 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int num1 = 0; 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int num2 = 0; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt(str.substr(0, num1_size), &num1) || 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !base::StringToInt(str.substr(num2_pos, num2_size), &num2)) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ret_num1 = num1; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ret_num2 = num2; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass WindowPlacementPrefUpdate : public DictionaryPrefUpdate { 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WindowPlacementPrefUpdate(PrefService* service, 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& window_name) 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : DictionaryPrefUpdate(service, prefs::kAppWindowPlacement), 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_name_(window_name) {} 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~WindowPlacementPrefUpdate() {} 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual base::DictionaryValue* Get() OVERRIDE { 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::DictionaryValue* all_apps_dict = DictionaryPrefUpdate::Get(); 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::DictionaryValue* this_app_dict = NULL; 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!all_apps_dict->GetDictionary(window_name_, &this_app_dict)) { 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this_app_dict = new base::DictionaryValue; 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci all_apps_dict->Set(window_name_, this_app_dict); 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return this_app_dict; 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string window_name_; 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(WindowPlacementPrefUpdate); 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string GetWindowName(const Browser* browser) { 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (browser->app_name().empty()) { 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return browser->is_type_popup() ? 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch prefs::kBrowserWindowPlacementPopup : prefs::kBrowserWindowPlacement; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return browser->app_name(); 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<DictionaryPrefUpdate> GetWindowPlacementDictionaryReadWrite( 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& window_name, 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PrefService* prefs) { 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!window_name.empty()); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // A normal DictionaryPrefUpdate will suffice for non-app windows. 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (prefs->FindPreference(window_name.c_str())) { 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return make_scoped_ptr( 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new DictionaryPrefUpdate(prefs, window_name.c_str())); 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return scoped_ptr<DictionaryPrefUpdate>( 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new WindowPlacementPrefUpdate(prefs, window_name)); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst base::DictionaryValue* GetWindowPlacementDictionaryReadOnly( 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& window_name, 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PrefService* prefs) { 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!window_name.empty()); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (prefs->FindPreference(window_name.c_str())) 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return prefs->GetDictionary(window_name.c_str()); 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::DictionaryValue* app_windows = 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci prefs->GetDictionary(prefs::kAppWindowPlacement); 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!app_windows) 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::DictionaryValue* to_return = NULL; 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci app_windows->GetDictionary(window_name, &to_return); 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return to_return; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldSaveWindowPlacement(const Browser* browser) { 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Only save the window placement of popups if the window is from a trusted 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // source (v1 app, devtools, or system window). 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return (browser->type() == Browser::TYPE_TABBED) || 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ((browser->type() == Browser::TYPE_POPUP) && browser->is_trusted_source()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveWindowPlacement(const Browser* browser, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& bounds, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::WindowShowState show_state) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save to the session storage service, used when reloading a past session. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we don't want to be the ones who cause lazy initialization of 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the session service. This function gets called during initial window 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // showing, and we don't want to bring in the session service this early. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionService* session_service = 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionServiceFactory::GetForProfileIfExisting(browser->profile()); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (session_service) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_service->SetWindowBounds(browser->session_id(), bounds, show_state); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetSavedWindowBoundsAndShowState(const Browser* browser, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect* bounds, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::WindowShowState* show_state) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browser); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bounds); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(show_state); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bounds = browser->override_bounds(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WindowSizer::GetBrowserWindowBoundsAndShowState(browser->app_name(), 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bounds, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_state); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool record_mode = parsed_command_line.HasSwitch(switches::kRecordMode); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool playback_mode = parsed_command_line.HasSwitch(switches::kPlaybackMode); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (record_mode || playback_mode) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In playback/record mode we always fix the size of the browser and 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // move it to (0,0). The reason for this is two reasons: First we want 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resize/moves in the playback to still work, and Second we want 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // playbacks to work (as much as possible) on machines w/ different 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // screen sizes. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bounds = gfx::Rect(0, 0, 800, 600); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The following options override playback/record. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parsed_command_line.HasSwitch(switches::kWindowSize)) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string str = 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parsed_command_line.GetSwitchValueASCII(switches::kWindowSize); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width, height; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ParseCommaSeparatedIntegers(str, &width, &height)) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds->set_size(gfx::Size(width, height)); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parsed_command_line.HasSwitch(switches::kWindowPosition)) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string str = 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parsed_command_line.GetSwitchValueASCII(switches::kWindowPosition); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, y; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ParseCommaSeparatedIntegers(str, &x, &y)) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds->set_origin(gfx::Point(x, y)); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chrome 171