root/chrome/browser/extensions/api/alarms/alarms_api.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ValidateAlarmCreateInfo
  2. owns_clock_
  3. owns_clock_
  4. RunImpl
  5. Callback
  6. RunImpl
  7. Callback
  8. RunImpl
  9. Callback
  10. RunImpl
  11. Callback
  12. RunImpl
  13. Callback

// 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/alarms/alarms_api.h"

#include "base/strings/string_number_conversions.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/alarms/alarm_manager.h"
#include "chrome/common/extensions/api/alarms.h"
#include "extensions/common/error_utils.h"

namespace alarms = extensions::api::alarms;

namespace extensions {

namespace {

const char kDefaultAlarmName[] = "";
const char kAlarmNotFound[] = "No alarm named '*' exists.";
const char kBothRelativeAndAbsoluteTime[] =
    "Cannot set both when and delayInMinutes.";
const char kNoScheduledTime[] =
    "Must set at least one of when, delayInMinutes, or periodInMinutes.";
const int kReleaseDelayMinimum = 1;
const int kDevDelayMinimum = 0;

bool ValidateAlarmCreateInfo(const std::string& alarm_name,
                             const alarms::AlarmCreateInfo& create_info,
                             const Extension* extension,
                             std::string* error,
                             std::vector<std::string>* warnings) {
  if (create_info.delay_in_minutes.get() &&
      create_info.when.get()) {
    *error = kBothRelativeAndAbsoluteTime;
    return false;
  }
  if (create_info.delay_in_minutes == NULL &&
      create_info.when == NULL &&
      create_info.period_in_minutes == NULL) {
    *error = kNoScheduledTime;
    return false;
  }

  // Users can always use an absolute timeout to request an arbitrarily-short or
  // negative delay.  We won't honor the short timeout, but we can't check it
  // and warn the user because it would introduce race conditions (say they
  // compute a long-enough timeout, but then the call into the alarms interface
  // gets delayed past the boundary).  However, it's still worth warning about
  // relative delays that are shorter than we'll honor.
  if (create_info.delay_in_minutes.get()) {
    if (*create_info.delay_in_minutes < kReleaseDelayMinimum) {
      COMPILE_ASSERT(kReleaseDelayMinimum == 1, update_warning_message_below);
      if (Manifest::IsUnpackedLocation(extension->location()))
        warnings->push_back(ErrorUtils::FormatErrorMessage(
            "Alarm delay is less than minimum of 1 minutes."
            " In released .crx, alarm \"*\" will fire in approximately"
            " 1 minutes.",
            alarm_name));
      else
        warnings->push_back(ErrorUtils::FormatErrorMessage(
            "Alarm delay is less than minimum of 1 minutes."
            " Alarm \"*\" will fire in approximately 1 minutes.",
            alarm_name));
    }
  }
  if (create_info.period_in_minutes.get()) {
    if (*create_info.period_in_minutes < kReleaseDelayMinimum) {
      COMPILE_ASSERT(kReleaseDelayMinimum == 1, update_warning_message_below);
      if (Manifest::IsUnpackedLocation(extension->location()))
        warnings->push_back(ErrorUtils::FormatErrorMessage(
            "Alarm period is less than minimum of 1 minutes."
            " In released .crx, alarm \"*\" will fire approximately"
            " every 1 minutes.",
            alarm_name));
      else
        warnings->push_back(ErrorUtils::FormatErrorMessage(
            "Alarm period is less than minimum of 1 minutes."
            " Alarm \"*\" will fire approximately every 1 minutes.",
            alarm_name));
    }
  }

  return true;
}

}  // namespace

AlarmsCreateFunction::AlarmsCreateFunction()
    : clock_(new base::DefaultClock()), owns_clock_(true) {}

AlarmsCreateFunction::AlarmsCreateFunction(base::Clock* clock)
    : clock_(clock), owns_clock_(false) {}

AlarmsCreateFunction::~AlarmsCreateFunction() {
  if (owns_clock_)
    delete clock_;
}

bool AlarmsCreateFunction::RunImpl() {
  scoped_ptr<alarms::Create::Params> params(
      alarms::Create::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  const std::string& alarm_name =
      params->name.get() ? *params->name : kDefaultAlarmName;
  std::vector<std::string> warnings;
  if (!ValidateAlarmCreateInfo(
          alarm_name, params->alarm_info, GetExtension(), &error_, &warnings)) {
    return false;
  }
  for (std::vector<std::string>::const_iterator it = warnings.begin();
       it != warnings.end(); ++it)
    WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_WARNING, *it);

  Alarm alarm(alarm_name,
              params->alarm_info,
              base::TimeDelta::FromMinutes(
                  Manifest::IsUnpackedLocation(GetExtension()->location()) ?
                  kDevDelayMinimum : kReleaseDelayMinimum),
              clock_->Now());
  AlarmManager::Get(GetProfile())->AddAlarm(
      extension_id(), alarm, base::Bind(&AlarmsCreateFunction::Callback, this));

  return true;
}

void AlarmsCreateFunction::Callback() {
  SendResponse(true);
}

bool AlarmsGetFunction::RunImpl() {
  scoped_ptr<alarms::Get::Params> params(alarms::Get::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
  AlarmManager::Get(GetProfile())
      ->GetAlarm(extension_id(),
                 name,
                 base::Bind(&AlarmsGetFunction::Callback, this, name));

  return true;
}

void AlarmsGetFunction::Callback(
    const std::string& name, extensions::Alarm* alarm) {
  if (alarm) {
    results_ = alarms::Get::Results::Create(*alarm->js_alarm);
    SendResponse(true);
  } else {
    error_ = ErrorUtils::FormatErrorMessage(kAlarmNotFound, name);
    SendResponse(false);
  }
}

bool AlarmsGetAllFunction::RunImpl() {
  AlarmManager::Get(GetProfile())->GetAllAlarms(
      extension_id(), base::Bind(&AlarmsGetAllFunction::Callback, this));
  return true;
}

void AlarmsGetAllFunction::Callback(const AlarmList* alarms) {
  if (alarms) {
    std::vector<linked_ptr<extensions::api::alarms::Alarm> > create_arg;
    create_arg.reserve(alarms->size());
    for (size_t i = 0, size = alarms->size(); i < size; ++i) {
      create_arg.push_back((*alarms)[i].js_alarm);
    }
    results_ = alarms::GetAll::Results::Create(create_arg);
  } else {
    SetResult(new base::ListValue());
  }
  SendResponse(true);
}

bool AlarmsClearFunction::RunImpl() {
  scoped_ptr<alarms::Clear::Params> params(
      alarms::Clear::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
  AlarmManager::Get(GetProfile())
      ->RemoveAlarm(extension_id(),
                    name,
                    base::Bind(&AlarmsClearFunction::Callback, this, name));

  return true;
}

void AlarmsClearFunction::Callback(const std::string& name, bool success) {
  SetResult(new base::FundamentalValue(success));
  SendResponse(true);
}

bool AlarmsClearAllFunction::RunImpl() {
  AlarmManager::Get(GetProfile())->RemoveAllAlarms(
      extension_id(), base::Bind(&AlarmsClearAllFunction::Callback, this));
  return true;
}

void AlarmsClearAllFunction::Callback() {
  SetResult(new base::FundamentalValue(true));
  SendResponse(true);
}

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */