// 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 "chromeos/memory/low_memory_listener.h"

#include <fcntl.h>

#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/sys_info.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/memory/low_memory_listener_delegate.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/zygote_host_linux.h"

using content::BrowserThread;

namespace chromeos {

namespace {
// This is the file that will exist if low memory notification is available
// on the device.  Whenever it becomes readable, it signals a low memory
// condition.
const char kLowMemFile[] = "/dev/chromeos-low-mem";

// This is the minimum amount of time in milliseconds between checks for
// low memory.
const int kLowMemoryCheckTimeoutMs = 750;
}  // namespace

////////////////////////////////////////////////////////////////////////////////
// LowMemoryListenerImpl
//
// Does the actual work of observing.  The observation work happens on the FILE
// thread, and notification happens on the UI thread.  If low memory is
// detected, then we notify, wait kLowMemoryCheckTimeoutMs milliseconds and then
// start watching again to see if we're still in a low memory state.  This is to
// keep from sending out multiple notifications before the UI has a chance to
// respond (it may take the UI a while to actually deallocate memory). A timer
// isn't the perfect solution, but without any reliable indicator that a tab has
// had all its parts deallocated, it's the next best thing.
class LowMemoryListenerImpl
    : public base::RefCountedThreadSafe<LowMemoryListenerImpl> {
 public:
  LowMemoryListenerImpl() : watcher_delegate_(this), file_descriptor_(-1) {}

  // Start watching the low memory file for readability.
  // Calls to StartObserving should always be matched with calls to
  // StopObserving.  This method should only be called from the FILE thread.
  // |low_memory_callback| is run when memory is low.
  void StartObservingOnFileThread(const base::Closure& low_memory_callback);

  // Stop watching the low memory file for readability.
  // May be safely called if StartObserving has not been called.
  // This method should only be called from the FILE thread.
  void StopObservingOnFileThread();

 private:
  friend class base::RefCountedThreadSafe<LowMemoryListenerImpl>;

  ~LowMemoryListenerImpl() {
    StopObservingOnFileThread();
  }

  // Start a timer to resume watching the low memory file descriptor.
  void ScheduleNextObservation();

  // Actually start watching the file descriptor.
  void StartWatchingDescriptor();

  // Delegate to receive events from WatchFileDescriptor.
  class FileWatcherDelegate : public base::MessageLoopForIO::Watcher {
   public:
    explicit FileWatcherDelegate(LowMemoryListenerImpl* owner)
        : owner_(owner) {}
    virtual ~FileWatcherDelegate() {}

    // Overrides for MessageLoopForIO::Watcher
    virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {}
    virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {
      LOG(WARNING) << "Low memory condition detected.  Discarding a tab.";
      // We can only discard tabs on the UI thread.
      BrowserThread::PostTask(BrowserThread::UI,
                              FROM_HERE,
                              owner_->low_memory_callback_);
      owner_->ScheduleNextObservation();
    }

   private:
    LowMemoryListenerImpl* owner_;
    DISALLOW_COPY_AND_ASSIGN(FileWatcherDelegate);
  };

  scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> watcher_;
  FileWatcherDelegate watcher_delegate_;
  int file_descriptor_;
  base::OneShotTimer<LowMemoryListenerImpl> timer_;
  base::Closure low_memory_callback_;

  DISALLOW_COPY_AND_ASSIGN(LowMemoryListenerImpl);
};

void LowMemoryListenerImpl::StartObservingOnFileThread(
    const base::Closure& low_memory_callback) {
  low_memory_callback_ = low_memory_callback;
  DCHECK_LE(file_descriptor_, 0)
      << "Attempted to start observation when it was already started.";
  DCHECK(watcher_.get() == NULL);
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(base::MessageLoopForIO::current());

  file_descriptor_ = ::open(kLowMemFile, O_RDONLY);
  // Don't report this error unless we're really running on ChromeOS
  // to avoid testing spam.
  if (file_descriptor_ < 0 && base::SysInfo::IsRunningOnChromeOS()) {
    PLOG(ERROR) << "Unable to open " << kLowMemFile;
    return;
  }
  watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher);
  StartWatchingDescriptor();
}

void LowMemoryListenerImpl::StopObservingOnFileThread() {
  // If StartObserving failed, StopObserving will still get called.
  timer_.Stop();
  if (file_descriptor_ >= 0) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    watcher_.reset(NULL);
    ::close(file_descriptor_);
    file_descriptor_ = -1;
  }
}

void LowMemoryListenerImpl::ScheduleNextObservation() {
  timer_.Start(FROM_HERE,
               base::TimeDelta::FromMilliseconds(kLowMemoryCheckTimeoutMs),
               this,
               &LowMemoryListenerImpl::StartWatchingDescriptor);
}

void LowMemoryListenerImpl::StartWatchingDescriptor() {
  DCHECK(watcher_.get());
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DCHECK(base::MessageLoopForIO::current());
  if (file_descriptor_ < 0)
    return;
  if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
          file_descriptor_,
          false,  // persistent=false: We want it to fire once and reschedule.
          base::MessageLoopForIO::WATCH_READ,
          watcher_.get(),
          &watcher_delegate_)) {
    LOG(ERROR) << "Unable to watch " << kLowMemFile;
  }
}

////////////////////////////////////////////////////////////////////////////////
// LowMemoryListener

LowMemoryListener::LowMemoryListener(LowMemoryListenerDelegate* delegate)
    : observer_(new LowMemoryListenerImpl),
      delegate_(delegate),
      weak_factory_(this) {
}

LowMemoryListener::~LowMemoryListener() {
  Stop();
}

void LowMemoryListener::Start() {
  base::Closure memory_low_callback =
      base::Bind(&LowMemoryListener::OnMemoryLow, weak_factory_.GetWeakPtr());
  BrowserThread::PostTask(
      BrowserThread::FILE,
      FROM_HERE,
      base::Bind(&LowMemoryListenerImpl::StartObservingOnFileThread,
                 observer_.get(),
                 memory_low_callback));
}

void LowMemoryListener::Stop() {
  weak_factory_.InvalidateWeakPtrs();
  BrowserThread::PostTask(
      BrowserThread::FILE,
      FROM_HERE,
      base::Bind(&LowMemoryListenerImpl::StopObservingOnFileThread,
                 observer_.get()));
}

void LowMemoryListener::OnMemoryLow() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  delegate_->OnMemoryLow();
}

}  // namespace chromeos
