feedbackDelegate.js
Go to the documentation of this file.
1 //
2 // BEGIN SONGBIRD GPL
3 //
4 // This file is part of the Songbird web player.
5 //
6 // Copyright(c) 2005-2008 POTI, Inc.
7 // http://songbirdnest.com
8 //
9 // This file may be licensed under the terms of of the
10 // GNU General Public License Version 2 (the "GPL").
11 //
12 // Software distributed under the License is distributed
13 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
14 // express or implied. See the GPL for the specific language
15 // governing rights and limitations.
16 //
17 // You should have received a copy of the GPL along with this
18 // program. If not, go to http://www.gnu.org/licenses/gpl.html
19 // or write to the Free Software Foundation, Inc.,
20 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //
22 // END SONGBIRD GPL
23 //
24 
30 Components.utils.import("resource://app/jsmodules/StringUtils.jsm");
31 
35 const PREF_APP_SESSIONS = "feedback.app_sessions";
36 const PREF_FIRST_OPENED_DATE = "feedback.first_opened_date";
37 const PREF_TOTAL_RUNTIME = "feedback.total_runtime";
38 const PREF_SURVEY_DATE = "feedback.survey_date";
39 const PREF_DISABLE_FEEDBACK = "feedback.disabled";
40 const PREF_DENIED_FEEDBACK = "feedback.denied";
41 const PREF_NEXT_FEEDBACK_MONTH_LAG = "feedback.next_feedback_month_lag";
42 const PREF_MIN_APP_SESSIONS = "feedback.min_app_sessions";
43 const PREF_MIN_TOTAL_RUNTIME = "feedback.min_total_runtime";
44 
48 const SURVEY_URL_KEY = "feedback.survey.url";
49 const MIN_APP_SESSIONS = 3;
50 const MIN_TOTAL_RUNTIME = 1800000; // 30 minutes
51 const STARTUP_DELAY = 5000; // 5 seconds
53 
57 var gObserverService = Components.classes["@mozilla.org/observer-service;1"]
58  .getService(Components.interfaces.nsIObserverService);
59 var gAppPrefs = Application.prefs;
60 
62 {
63  return parseInt(gAppPrefs.getValue(name, value || 0).toString(), 10);
64 }
65 
69 function FeedbackDelegate()
70 {
71  var self = this;
72  setTimeout(function() { self._init(); }, STARTUP_DELAY);
73 }
74 
75 FeedbackDelegate.prototype =
76 {
77  _mAppStartTimespec: 0,
78  _mSavedTotalRuntime: 0,
79  _mHasSessionRequirements: false,
80  _mHasRuntimeRequirements: false,
81 
82  _init: function()
83  {
84  // If feedback has been disabled (i.e. debug build), just exit.
85  var disablePrefs = gAppPrefs.get(PREF_DISABLE_FEEDBACK);
86  if (disablePrefs != null && disablePrefs.value) {
87  return;
88  }
89 
90  // Don't show the feedback dialog again if the user turned down feedback.
91  if (gAppPrefs.has(PREF_DENIED_FEEDBACK)) {
92  return;
93  }
94 
95  // Don't show the feedback dialog if we don't know where to send the survey
96  if ("false" == SBString(SURVEY_URL_KEY, "false", SBStringGetBrandBundle())) {
97  return;
98  }
99 
100  var curDate = new Date();
101  this._mAppStartTimespec = curDate.getTime();
102  var hasDateRequirements = true;
103 
104  // If the user has already taken the survey, only procede showing it again
105  // after six months.
106  if (gAppPrefs.has(PREF_SURVEY_DATE)) {
107  var surveyTakenTime =
108  parseInt(gAppPrefs.get(PREF_SURVEY_DATE).value);
109 
110  var surveyTakenDate = new Date();
111  surveyTakenDate.setTime(surveyTakenTime);
112 
113  var futureDate = new Date();
114  futureDate = new Date();
115  futureDate.setTime(surveyTakenTime);
116 
117  // JS Date range is 0-11
118  var futureMonthLag = surveyTakenDate.getUTCMonth() +
119  getPrefValue(PREF_NEXT_FEEDBACK_MONTH_LAG,
121  if (futureMonthLag >= 12) {
122  futureMonthLag -= 12;
123  // Since this is roll over, bump the year
124  futureDate.setUTCFullYear(futureDate.getUTCFullYear() + 1);
125  }
126  futureDate.setUTCMonth(futureMonthLag);
127 
128  // If the timeframe has not passed the 6 month mark, bail.
129  if (curDate.getTime() <= futureDate.getTime()) {
130  return;
131  }
132  }
133 
134  // Check to see if we are not on the same day we first opened the app.
135  if (gAppPrefs.has(PREF_FIRST_OPENED_DATE)) {
136  var firstSessionTime =
137  parseInt(gAppPrefs.get(PREF_FIRST_OPENED_DATE).value);
138 
139  var firstSessionDate = new Date();
140  firstSessionDate.setTime(firstSessionTime);
141 
142  if (curDate.getUTCDate() == firstSessionDate.getUTCDate() &&
143  curDate.getUTCMonth() == firstSessionDate.getUTCMonth() &&
144  curDate.getUTCFullYear() == firstSessionDate.getUTCFullYear())
145  {
146  hasDateRequirements = false;
147  }
148  }
149  else {
150  // First time application was launched, we need to save the current date.
151  gAppPrefs.setValue(PREF_FIRST_OPENED_DATE, "" + curDate.getTime());
152  }
153 
154  var numSessions = getIntPrefValue(PREF_APP_SESSIONS);
156  {
157  this._mHasSessionRequirements = true;
158  }
159 
160  this._mSavedTotalRuntime = getIntPrefValue(PREF_TOTAL_RUNTIME);
161  if (this._mSavedTotalRuntime >= getIntPrefValue(PREF_MIN_TOTAL_RUNTIME,
163  {
164  this._mHasRuntimeRequirements = true;
165  }
166 
167  if (this._mHasSessionRequirements &&
168  this._mHasRuntimeRequirements)
169  {
170  // Only show the survey if we met the date requirments. If not, we'll
171  // have to wait until the next day the app is started.
172  //
173  // To work around a scenario where the only window in th window registry
174  // is the hidden window, wait 10 seconds to show the dialog.
175  // @see bug 9887
176  if (hasDateRequirements) {
177  var self = this;
178  setTimeout(function() { self._showSurvey(); }, 10000);
179  }
180  }
181  else {
182  gObserverService.addObserver(this, "quit-application-granted", false);
183  }
184  },
185 
186  _showSurvey: function()
187  {
188  var retVal = { shouldLoadSurvey: false};
189 
190  var winMediator =
191  Components.classes["@mozilla.org/appshell/window-mediator;1"]
192  .getService(Components.interfaces.nsIWindowMediator);
193 
194  var mainWin = winMediator.getMostRecentWindow("Songbird:Main");
195  if (mainWin && mainWin.window && mainWin.window.gBrowser) {
196  mainWin.openDialog("chrome://songbird/content/xul/feedbackDialog.xul",
197  "feedback-dialog",
198  "chrome,modal=yes,centerscreen,resizable=false",
199  retVal);
200 
201  // Mark the survey date
202  gAppPrefs.setValue(PREF_SURVEY_DATE, "" + new Date().getTime());
203 
204  if (retVal.shouldLoadSurvey) {
205  var surveyURL = SBString(SURVEY_URL_KEY, "false", SBStringGetBrandBundle());
206  mainWin.window.gBrowser.loadURI(surveyURL, null, null, null, "_blank");
207  mainWin.focus();
208  }
209  else {
210  gAppPrefs.setValue(PREF_DENIED_FEEDBACK, true);
211 
212  // Flush to disk to make sure the dialog won't be shown again in the
213  // event of a crash. See bug 11857.
214  var prefService =
215  Components.classes["@mozilla.org/preferences-service;1"]
216  .getService(Components.interfaces.nsIPrefService);
217  if (prefService) {
218  // Passing null uses the currently loaded pref file.
219  // (usually 'prefs.js')
220  prefService.savePrefFile(null);
221  }
222  }
223  }
224  },
225 
226  observe: function(aSubject, aTopic, aData)
227  {
228  if (aTopic != "quit-application-granted")
229  return;
230 
231  // We are shutting down - it's now time to save the elapsed time to our
232  // runtime variable and increment the session count. Note that we only
233  // should update these prefs if the requirements have not been met when
234  // the application started up.
235  if (!this._mHasRuntimeRequirements) {
236  var curTimespec = new Date().getTime();
237  var elapsedTime = curTimespec - this._mAppStartTimespec;
238 
239  gAppPrefs.setValue(PREF_TOTAL_RUNTIME,
240  "" + (this._mSavedTotalRuntime + elapsedTime));
241  }
242 
243  if (!this._mHasSessionRequirements) {
244  var curSessionCount = getIntPrefValue(PREF_APP_SESSIONS);
245  gAppPrefs.setValue(PREF_APP_SESSIONS, (curSessionCount + 1));
246  }
247 
248  gObserverService.removeObserver(this, "quit-application-granted");
249  },
250 
251  QueryInterface: function(iid)
252  {
253  if (!iid.equals(Components.interfaces.nsIObserver) &&
254  !iid.equals(Components.interfaces.nsISupports))
255  {
256  throw Components.results.NS_ERROR_NO_INTERFACE;
257  }
258 
259  return this;
260  }
261 };
262 
263 // initialize a new feedback delegate (no need for a refernce to it)
264 new FeedbackDelegate();
const PREF_DISABLE_FEEDBACK
const PREF_TOTAL_RUNTIME
var Application
Definition: sbAboutDRM.js:37
const PREF_SURVEY_DATE
const PREF_NEXT_FEEDBACK_MONTH_LAG
function getIntPrefValue(name, value)
const SURVEY_URL_KEY
function FeedbackDelegate()
sbOSDControlService prototype QueryInterface
const MIN_APP_SESSIONS
function SBStringGetBrandBundle()
function SBString(aKey, aDefault, aStringBundle)
Definition: StringUtils.jsm:93
const PREF_APP_SESSIONS
const PREF_MIN_TOTAL_RUNTIME
const PREF_DENIED_FEEDBACK
const PREF_MIN_APP_SESSIONS
const NEXT_FEEDBACK_MONTH_LAG
aWindow setTimeout(function(){_this.restoreHistory(aWindow, aTabs, aTabData, aIdMap);}, 0)
const STARTUP_DELAY
var gObserverService
return null
Definition: FeedWriter.js:1143
const MIN_TOTAL_RUNTIME
countRef value
Definition: FeedWriter.js:1423
const PREF_FIRST_OPENED_DATE
var gAppPrefs
_updateTextAndScrollDataForFrame aData
sbDeviceFirmwareAutoCheckForUpdate prototype observe